Shaker排序的酒吧演示一次排序所有酒吧-Java

时间:2017-12-04 06:34:17

标签: java swing sorting user-interface

我在接受的答案中找到了此代码:Java swing repainting while computing: animating sorting algorithm

我一直在尝试修改它,因此它适用于振动器排序,但我的代码会立即对所有内容进行排序。

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class ShakerSortAnimate extends JPanel {
private static final int NUM_OF_ITEMS = 20;
private static final int DIM_W = 400;
private static final int DIM_H = 400;
private static final int HORIZON = 350;
private static final int VERT_INC = 15;
private static final int HOR_INC = DIM_W / NUM_OF_ITEMS;

private JButton startButton;
private Timer timer = null;
private JButton resetButton;

Integer[] list;
int currentIndex = NUM_OF_ITEMS - 1;

public ShakerSortAnimate() {
    list = initList();

    timer = new Timer(200, new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            if (isSortingDone()) {
                ((Timer) e.getSource()).stop();
                startButton.setEnabled(false);
            } else {
                sortOnlyOneItem();
            }
            repaint();
        }
    });

    //button to run the program
    startButton = new JButton("Start");
    startButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            timer.start();
        }
    });

    //resets screen
    resetButton = new JButton("Reset");
    resetButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            list = initList();
            currentIndex = NUM_OF_ITEMS - 1;
            repaint();
            startButton.setEnabled(true);
        }
    });
    add(startButton);
    add(resetButton);
}

//boolean checks when array is sorted
public boolean isSortingDone() {
    return currentIndex == 0;
}

//initializes the array
public Integer[] initList() { 
    Integer[] nums = new Integer[NUM_OF_ITEMS];
    for (int i = 1; i <= nums.length; i++) {
        nums[i - 1] = i;
    }
    Collections.shuffle(Arrays.asList(nums)); //shuffles array
    return nums;
}

//draws each bar
public void drawItem(Graphics g, int item, int index) {
    int height = item * VERT_INC;
    int y = HORIZON - height;
    int x = index * HOR_INC;
    g.fillRect(x, y, HOR_INC, height);
}


//My shaker sort code
public void sortOnlyOneItem()
{
    boolean swapped = true;
    int start = 0;
    int end = currentIndex;

    while (swapped==true)
    {
        swapped = false;

        for (int i = start; i < end; ++i)
        {
            if (list[i] > list[i + 1])
            {
                int temp = list[i];
                list[i] = list[i+1];
                list[i+1] = temp;
                swapped = true;
            }
        }

        if (swapped==false)
            break;

        swapped = false;

        end = end-1;

        for (int i = end; i >=start; i--)
        {
            if (list[i] > list[i+1])
            {
                int temp = list[i];
                list[i] = list[i+1];
                list[i+1] = temp;
                swapped = true;
            }
        }

        start = start + 1;
    }

   currentIndex--; //currentIndex is updated each time shaker sort runs
}






//draws all bars
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    for (int i = 0; i < list.length; i++) {
        drawItem(g, list[i], i);
    }
}

@Override
public Dimension getPreferredSize() {
    return new Dimension(DIM_W, DIM_H);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            JFrame frame = new JFrame("Sort");
            frame.add(new ShakerSortAnimate());
            frame.pack();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}
  }

我确实意识到我的Shaker Sort代码必须为每次比较做,而不是整个事情,但老实说,我甚至不知道如何开始编码。如果你们这里的任何人都知道如何在振动筛排序中对每个比较进行编码,你能帮助我吗?

是的,我发布了整个内容,所以你也可以尝试运行它。

提前致谢!

1 个答案:

答案 0 :(得分:1)

所以,你需要这个......

public void sortOnlyOneItem()
{
    boolean swapped = true;
    int start = 0;
    int end = currentIndex;

    while (swapped==true)
    {
        swapped = false;

        for (int i = start; i < end; ++i)
        {
            if (list[i] > list[i + 1])
            {
                int temp = list[i];
                list[i] = list[i+1];
                list[i+1] = temp;
                swapped = true;
            }
        }

        if (swapped==false)
            break;

        swapped = false;

        end = end-1;

        for (int i = end; i >=start; i--)
        {
            if (list[i] > list[i+1])
            {
                int temp = list[i];
                list[i] = list[i+1];
                list[i+1] = temp;
                swapped = true;
            }
        }

        start = start + 1;
    }

   currentIndex--; //currentIndex is updated each time shaker sort runs
}

每次通话仅运行ONCE。它现在没有这样做,因为如果while-loop,我们需要摆脱它。

这样做时,只有在swappedtrue的情况下才能运行第二个循环,并且currentIndex只应在swapped仍为true的情况下递减

这给我们带来了类似......

public void sortOnlyOneItem() {
    boolean swapped = true;
    int start = 0;
    int end = currentIndex;

    for (int i = start; i < end; ++i) {
        if (list[i] > list[i + 1]) {
            int temp = list[i];
            list[i] = list[i + 1];
            list[i + 1] = temp;
            swapped = true;
        }
    }

    if (swapped) {
        swapped = false;

        end = end - 1;

        for (int i = end; i >= start; i--) {
            if (list[i] > list[i + 1]) {
                int temp = list[i];
                list[i] = list[i + 1];
                list[i + 1] = temp;
                swapped = true;
            }
        }
    }

    if (swapped) {
        currentIndex--; //currentIndex is updated each time shaker sort runs
    }
}

这仍然不太正确,因为两个for-loop可以进行多项更改。

相反,我们需要一个迭代,它最多只能进行两次更改,一次是开始,一次是结束

哪个,可能看起来像......

protected void swap(int a, int b) {
    int tmp = list[a];
    list[a] = list[b];
    list[b] = tmp;
}

int endIndex = NUM_OF_ITEMS - 1;

//My shaker sort code
public void sortOnlyOneItem() {

    int startIndex = 0;
    while (startIndex < NUM_OF_ITEMS - 1 && list[startIndex] < list[startIndex + 1]) {
        startIndex++;
    }

    if (startIndex < NUM_OF_ITEMS - 1 && list[startIndex] > list[startIndex + 1]) {
        swap(startIndex, startIndex + 1);
        int end = endIndex;
        while (end > 0 && list[end - 1] < list[end]) {
            end--;
        }
        if (end > 0 && list[end - 1] > list[end]) {
            swap(end - 1, end);
        } else {
            endIndex--;
        }
    } else {
        endIndex = 0;
    }
}

现在,这基本上会查找可能可更改的两个索引(如果可能,可以更改startend)和swap。当您可以从start迭代到最终而不进行更改时,排序就完成了。

现在,我没有声明是否准确,只是它尽最大努力模仿你提供的算法