8

我实现了不同类型的排序(冒泡、插入、选择)。知道我想为每种排序比较它们的实现,如下所示(这是冒泡排序的示例):

在此处输入图像描述

例如,这是我的冒泡排序:

private static int[] bubbleSort(int[] tabToSort) {
   int [] tab = tabToSort.clone();
   boolean tabSort = false;
   while(!tabSort){
        tabSort = true;
        for(int i = 0; i < tab.length -1; i++){
            if(tab[i]> tab[i+1]){
                int temp = tab[i+1];
                tab[i+1] = tab[i];
                tab[i] = temp;
                tabSort = false;
            }
        }
    }
    return tab;
}

我启动了 GUI,并在其上放置了 1000 个随机点和行y=x

@Override
    public void paintComponent (Graphics g){
        super.paintComponent(g);
        Graphics2D g2d  = (Graphics2D) g;
        g2d.setColor(Color.BLACK);
        Dimension size = getSize();
        Insets  insets= getInsets();
        int w =  size.width - insets.left - insets.right;
        int h =  size.height - insets.top - insets.bottom;
        
        g2d.drawLine(size.width ,0, 0, size.height);
        Random r = new Random();

        for (int i  =0; i < 1000; i++) {
           int x = Math.abs(r.nextInt()) % w;
           int y = Math.abs(r.nextInt()) % h;
           Point p = new Point(x, y);
           g2d.drawLine(p.x, p.y, p.x, p.y);
        }
    }

这是我所做的:

在此处输入图像描述

现在我被卡住了,我不知道如何开始。谁能告诉我要遵循的步骤/提示来实现它?

谢谢 :)

4

4 回答 4

4

您必须定义这些点的含义。查看动画,看起来 y 轴代表 a value,而 x 轴代表该position值的数组中的 。

在您的paint方法中,您将浏览项目列表并绘制一个点,其中 x 点是数组中的位置,y 点是 y 轴上的位置。假设值在已知范围内。

另外,请记住图形中的 y 轴从顶部的 0 开始,因此您可能需要将值转换为坐标(取决于您希望它的外观)。

于 2013-05-26T15:28:20.230 回答
1

我已经为我的学士学位做了这个,我是这样做的(它并不完美,但它可能会对你有所帮助):

(我从下面的代码中删除了一些不重要的方法/函数。主要是为了说明我是如何将其可视化的。例如,您可以将 GRectangle 类替换为简单的 java.awt.Point 类。)

初始化方法为您提供了一个示例,说明如何找到数据的最大值和最小值,以便您知道如何转换 datavalues => 坐标。

public class DotVisualisation extends Visualisation {

    private ArrayList<GRectangle> m_points;

    private Comparable[] m_data;

    private Comparable m_maxValue;
    private Comparable m_minValue;

    private int MAX_HEIGHT; // max height in pixels of visualization

    /**
     * Creates a new DotVisualisation.<br>
     * <br>
     * This class is a runnable JComponent that will visualize data as a function. 
     * The visualisation will plot the data with X and Y coordinates on the window. 
     * The X coordinate of the point is index of the dataelement. 
     * The Y coordinate of the point is relative to the value of the dataelement.<br>
     * <br>
     * This visualisation should be used for medium and large arrays.
     * 
     * @author David Nysten
     */
    public DotVisualisation()
    {
        m_points = new ArrayList<GRectangle>();
        MAX_HEIGHT = 150;
    }

    /**
     * Returns the maximum supported dimension by this visualisation.
     * 
     * @return The supported dimension.
     */
    public static int getSupportedDimension()
    {
        return 1;
    }

    @Override
    public Dimension getMaximumSize() 
    {
        return getPreferredSize();
    }

    @Override
    public Dimension getPreferredSize() 
    {
        return new Dimension(m_points.size() + 2, MAX_HEIGHT + 6);
    }

    @Override
    public Dimension getMinimumSize() 
    {
        return getPreferredSize();
    }

    @Override
    public void paintComponent(Graphics g)
    {
        for(int i = 0; i < m_points.size(); ++i)
            m_points.get(i).paintComponent(g);
    }

    private void swap(int index, int index2) { // See below }

    private void initialise()
    {
        findMinimum();
        findMaximum();
        m_points.clear();
        double multiplier;
        int x = 0, y = 0, h;
        for(int i = 0; i < m_data.length; ++i)
        {
            if(m_data[i].compareTo(-1) <= 0)
                h = 0;
            else
            {
                Integer value = (Integer) m_data[i];
                Integer min = (Integer) m_minValue;
                Integer diff = (Integer) m_maxValue - min;
                multiplier = MAX_HEIGHT / diff.doubleValue();
                h = (int) ((value - min) * multiplier);
            }
            y = (int) (MAX_HEIGHT - h);
            GRectangle r = new GRectangle(x, y, 1, 1); // 1, 1 = width and height
            r.setColor(Color.BLACK);
            m_points.add(r);
            ++x;
        }
    }

    private void findMaximum()
    {
        Comparable max = null;
        if(m_data.length > 0)
        {
            max = m_data[0];
            for(int i = 1; i < m_data.length; ++i)
                if(m_data[i].compareTo(max) > 0)
                    max = m_data[i];
        }
        m_maxValue = max;
    }

    private void findMinimum()
    {
        Comparable min = null;
        if(m_data.length > 0)
        {
            min = m_data[0];
            for(int i = 1; i < m_data.length; ++i)
                if(m_data[i].compareTo(min) < 0)
                    min = m_data[i];
        }
        m_minValue = min;
    }
}

考虑到这一点:在 150 像素的高度上可视化 0 到 150 之间的整数很简单。在 150 的高度上可视化一组介于 565 和 3544545 之间的整数有点少。

PS:代码使用inputarray中元素的索引作为X坐标。
PS:该类保留对输入数组(m_​​data 变量)的引用,但这当然不是必需的,您只需要它来初始化您的点。
PS:我的所有可视化扩展的“可视化”类基本上是一个JPanel。
PS:上面的代码是为正整数编写的,因此可能还需要一些额外的编码来处理负整数;)。

然后为了可视化算法的动作,我使用了观察者模式。该算法(例如冒泡排序)如下所示:

    for(int i = 0; i < size(); ++i)
        for(int j = 1; j < size(); ++j)
            if(greaterThan(j - 1, j))
                swap(j - 1, j);

其中swap函数定义如下(再次简化版):

protected void swap(int index1, int index2)
{
    if(index1 != index2)
    {
        incrementSwap(); // counting swaps and visualizing counter

        m_command.clear();
        m_command.setAction(Action.SWAP);
        m_command.addParameter(index1);
        m_command.addParameter(index2);
        setChanged();
        notifyObservers(m_command);

        E temp = m_data[index1];
        m_data[index1] = m_data[index2];
        m_data[index2] = temp;
    }
}

我通知我的观察者(可视化)在 index1 和 index2 上发生了交换。m_command 变量是 Command 类的一个实例(我自己编写的),它只是可视化所需信息的包装器。即:发生的动作和相关信息(例如交换动作的索引)。

因此,在可视化中,我交换了这些索引上的 GRectangle 以及它们的 X 坐标;

private void swap(int index, int index2)
{
    if(index == index2)
        return;
    GRectangle r1 = m_points.get(index);
    GRectangle r2 = m_points.get(index2);

    int tempX = r1.getX();
    r1.setLocation(r2.getX(), r1.getY());
    r2.setLocation(tempX, r2.getY());

    m_points.set(index, r2);
    m_points.set(index2, r1);
}

您可以像这样添加行:

        try {
            Thread.sleep(100);
        } catch(InterruptedException ignore) {}

让线程在继续之前休眠 100 毫秒。如果可视化太快,这可能会派上用场。

因此,对于具有随机整数的数组,它可能如下所示:

在此处输入图像描述

排序后:(当然这不是一条直线,因为在这种情况下,输入数组中的值是随机生成的)

在此处输入图像描述

因此,如果您必须 - 就像我必须 - 允许多个算法使用相同的可视化,我可以建议您将可视化类和算法类分开,并使用观察者模式让可视化在动作发生时更新(设置,交换,...​​)。

然后你可以创建这样的东西进行比较;

http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany_zps63269d2a.png http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany2_zps65e96fa9.png

祝你好运!

于 2013-05-26T17:11:31.693 回答
1

最简单的方法是将您的绘画方法转换为使用预定义List点作为参数而不是随机点的方法。在您的 sort 方法的每次迭代中,将排序后的数组传递给 paint 方法并重新绘制点。

于 2013-05-26T15:26:40.517 回答
1

你需要

  1. 创建一个int[] 以随机值作为成员变量的数组。让我们调用数组data。您可能希望从一个固定的数组大小和每个 100 的范围开始。当一个简单的版本工作时,您可以稍后将这些值调整为窗口大小。坚持固定大小和范围并仅缩放到可用空间可能会更好paintComponent,从而使行为独立于窗口大小。
  2. 改为paintComponent循环data。循环索引是您的 x 值并data[x]确定 y 值。
  3. 测试代码是否仍然绘制初始随机数组。不在乎它现在是否在左上角,您可以在动画工作时修复它。
  4. 您需要在sleep()排序方法的最内层循环中添加某种调用,以便您有机会观察这些步骤。否则,即使是冒泡排序也会太快而无法观察。我建议从一秒开始(参数值 1000)。当一切正常时,让它更快。
  5. 在新线程中启动该bubbleSort方法,并确保您的组件在每一步都重新绘制。这可能是最棘手的部分。或许将组件交给bublleSort方法(或制作组件bubbleSort的非静态方法)并让它repaint()在每一步都请求一个(幸运的是,这是 Swing 中为数不多的线程安全方法之一)。
  6. 微调您的代码:通过乘以可用空间然后除以数组大小或值范围来缩放 x 和 y 坐标。根据需要调整睡眠时间。添加对不同排序算法的支持....

如果有任何步骤不清楚,请添加评论。

于 2013-05-26T15:47:33.833 回答