SelectionSort变体不起作用

时间:2014-11-11 09:02:03

标签: java arrays sorting selection-sort

我必须根据以下参数在Java中实现Selection Sort:

  

为SelectionSort实现一个变体,它在扫描列表时分别定位最小和最大元素,并将它们分别放在列表的开头和结尾。在第一个通道上,扫描元素x0,...,xn-1;在第二个传递中,扫描元素x1,...,xn-2;等等。

我传递的方法是一个大小为32的数组,当我打印数组时,它没有被排序。我的代码有什么问题?

static void selectionSort() {
    scramble();
    int smallIndex = 0;  //index of smallest to test
    int largeIndex = array.length - 1;  //index of largest to test
    int small = 0;  //smallest
    int large;  //largest
    int smallLimit = 0;  //starts from here
    int largeLimit = array.length - 1;  //ends here
    int store;  //temp stored here
    int store2;

    for(int i = 0; i < array.length/2; i++) {  //TODO not working...
        small = array[smallLimit];
        large = array[largeLimit];
        for(int j = smallLimit; j <= largeLimit; j++) {
            if(array[j] < small) {
                smallIndex = j;
                small = array[j];
            }
            else if(array[j] > large) {
                largeIndex = j;
                large = array[j];
            }
        }
        store = array[smallLimit];
        store2 = array[smallIndex];
        array[smallLimit] = store2;
        array[smallIndex] = store;
        store = array[largeLimit];
        array[largeLimit] = array[largeIndex];
        array[largeIndex] = store;
        smallLimit++;
        largeLimit--;
    }
    print();    
}

2 个答案:

答案 0 :(得分:1)

考虑极端情况:在smallLimitlargeLimit找到最大或最小的项目时会发生什么。当发生这种情况时,你有两个问题:

  1. largeIndexsmallIndex未设置。它们保留了之前迭代的值。
  2. 将最小的项目交换到正确的位置会移动最大的项目。第二个交换移动最大应该去的最小项目,最大项目在随机位置结束。如果您发现难以想象,请在纸上或调试器中逐步完成代码。
  3. 这些问题很容易解决。您可以按照一些准则避免此问题:

    • 使用较少的活动部件。您始终可以使用small获取smallIndex的值,如果您刚使用smallIndex,则不会有不同变量失步的危险。
    • 在尽可能小的范围内声明变量。如果在循环体中声明smallIndex而不是在编译器之外,那么编译器会告诉你在交换之前没有设置它。
    • 像第一次交换这样的破坏性更新总是可以使先前的计算过时。当你无法避免这种情况发生时,寻找两种更新可以互相踩到脚趾的方式。

答案 1 :(得分:0)

就像@Joni明确指出的那样,在遍历数组期间,交换两个两次元素存在很大的警告。由于您必须实现排序算法就地,因此您需要在连续发生时考虑要交换的元素的位置。

您需要看到的另一个限制情况是,只剩下三个元素,即for循环的最后一次迭代。我就是这样做的:

    store = array[smallLimit];
    store2 = array[smallIndex];
    array[smallLimit] = small;
    array[smallIndex] = store;
    smallLimit++;
    //No problem with swapping the first two elements
    store = array[largeLimit];

    //However the first swap might cause the other elements to shift
    //So we do this check
    if((array[largeIndex] == large))
     {array[largeLimit] = array[largeIndex];
      array[largeIndex] = store;
      largeLimit--;
     }

    //Just a limiting case, where amongst the last three elements, first swap happens. 
    //The smallest element is in place, just take care of the other two elements.
    if(largeLimit - smallLimit == 1){
        if(array[largeLimit] != large){
            array[smallLimit] = array[largeLimit];
            array[largeLimit] = large;
            largeLimit--;
        }
    }

根据您的代码构建DEMO以获取上述代码段。希望它能让你开始朝着正确的方向前进。