数组的选择排序方法

时间:2014-01-17 20:25:12

标签: java arrays recursion

我有这个方法,我从一个关于选择排序的网站,我需要检查它的工作原理:

import java.util.Arrays;

public class SelectionSort {
public static void selectionSort(int[] data, int low, int high) {
    if (low < high) {
        swap(data, low, findMinIndex(data, low));
        selectionSort(data, low + 1, high);
    }
}

public static void swap(int[] array, int index1, int index2) {
    int tmp = array[index1];
    array[index1] = array[index2];
    array[index2] = tmp;
}

public static int findMinIndex(int[] data, int index) {
        int minIndex;
        if (index == data.length - 1)
        return index;
        minIndex = findMinIndex(data, index + 1);
        if (data[minIndex] < data[index])
        return minIndex;
        else
        return index;
}



public static void main (String[] args) {
    int[] numbers = {3, 15, 1, 9, 6, 12, 21, 17, 8}; 
    SelectionSort.selectionSort(numbers, 0, numbers.length);
    System.out.println(Arrays.toString(numbers));
}
}

你能帮助我吗?为什么int high得到数组的最后一个索引?怎么样?

3 个答案:

答案 0 :(得分:3)

在此特定代码中......

findMinIndex将给定索引中的元素与其前面的所有元素(具有更高索引的元素)进行比较,直到数组的最后一个元素。

所以如果你有一个数组:

int[] a = { 7, 4, 2, 6 };

并且你调用findMinIndex(a, 0);它将首先检查索引0后面是否有一个元素。这就是这部分index == data.length - 1的作用。如果之后没有元素,它将只返回它传递的index。但是由于数组长度为4,因此在索引0之后显然有一个元素。

现在我们已经确认在index之后有元素,现在是时候在index之后得到最小元素的索引了。通过这种方式,我们可以将index处的元素与其前面的所有元素进行比较,以查看indexarray.length - 1(包括)范围内哪个元素最小。这是通过递归完成的:

minIndex = findMinIndex(data, index + 1);

接下来的几个电话会是这样的:

findMinIndex(data, 1);
// is there an element after 1? There is. So we end up calling findMinIndex again...

findMinIndex(data, 2); // is there an element after 2? Yes. Recurse...

findMinIndex(data, 3); // is there an element after 3? No. That's the end of the array

// remember this part? it's used now to finally terminate the recursion
if (index == data.length - 1)
    return index; // this equals 3

现在递归调用开始展开。

// index == 2 because the 2nd to last index is 2. remember our array has length 4 and indices 0-3.
minIndex = 3; // this is the index of the last element
if (data[3] < data[2]) { // look at our array 'a', is 6 less than 2?
    return 3; // No it is not. so this is not returned
} else {
    return 2; // we end up return the index (2) of the smaller element (2)
}

再次展开。

// index == 1
minIndex = 2; // we compared 2 and 3 and found that the element at index 2 was smaller
if (data[2] < data[1]) { // is 2 less than 4?
    return 2; // yes, this is returned because the element at index 2 is less than the element at index 1
} else {
    return 1; // false!
}

还有一次。

// index == 0 this is our original call! when we said findMinIndex(a, 0);
minIndex = 2;
if (data[2] < data[0]) { // is 2 less than 7?
    return 2; // yes it is
} else {
    return 0; // false!
}

最后,该方法将返回2.这是因为在(包括)索引0之后的所有元素,索引为2的元素是最小的。

现在让我们看一下selectionSort。首次调用时,需要使用以下格式:

selectionSort(a, 0, 4); // where 4 is the length of the array

此函数也使用递归。交换方法是自解释的(它将元素交换为2个不同的索引)。现在让我们来看看递归调用:

if (0 < 4) { // True of course
    swap(a, 0, findMinIndex(a, 0));
    selectionSort(data, 0 + 1, 4);
}

请记住,我们发现0(含)之后的最小元素的索引为2.所以上面的代码可以替换为:

if (0 < 4) { // True of course
    swap(a, 0, 2);
    selectionSort(data, 0 + 1, 4);
}

这会将我们的数组更改为{2, 4, 7, 6},因为我们交换了索引0和索引2处的元素。请注意索引0现在是数组中值为2的最小元素。

现在再次调用selectionSort以确保数组的顺序从最小到最大。下一个电话会是这样的:

// low == 1 and high == 4
if (1 < 4) { // true
    swap(a, 1, findMinIndex(data, 1));
    selectionSort(a, 1 + 1, 4);
}

请记住我们的数组现在是{2, 4, 7, 6}。这意味着索引1(值为4)之后的最小元素实际上只是4.所以上面的代码将等于:

// low == 1 and high == 4
if (1 < 4) { // true
    swap(a, 1, 1);
    selectionSort(a, 1 + 1, 4);
}

在这种情况下,交换不执行任何操作。现在再次递归调用该方法。

// low == 2 and high == 4
if (2 < 4) { // true
    swap(a, 2, findMinIndex(data, 2));
    selectionSort(a, 2 + 1, 4);
}

我们的数组在最后一次交换时没有改变。索引2(包括)之后的最小元素将是6,其索引为3.这意味着我们的代码等于:

// low == 2 and high == 4
if (2 < 4) { // true
    swap(a, 2, 3);
    selectionSort(a, 2 + 1, 4);
}

现在我们的数组变为{ 2, 4, 6, 7 }。万岁,从最小到最大!但那不是结束的地方。还有一个递归调用只是为了确保它真的有序。

// low == 3 and high == 4
if (3 < 4) { // true
    swap(a, 3, findMinIndex(data, 3));
    selectionSort(a, 3 + 1, 4);
}

请记住在findMinIndex中检查给定索引后是否有任何元素?索引3后面没有元素,所以它只返回3.这意味着上面的代码等于:

// low == 3 and high == 4
if (3 < 4) { // true
    swap(a, 3, 3);
    selectionSort(a, 3 + 1, 4);
}

此交换不执行任何操作。正如你所看到的,还有另一个递归调用!这将是最后一个。

// low == 4 and high == 4
if (4 < 4) { // false, 4 is not less than 4
    swap(a, 4, findMinIndex(a, 4)); // none of this happens
    selectionSort(a, 4 + 1, 4); // no recursion
}
// finally returns void

结束。

通过循环而不是递归来理解选择排序要容易得多。

答案 1 :(得分:1)

它是数组的大小,用于知道何时结束。

每个周期: 第一:检查是否有任何元素和索引高于低(低开始于0)是否更低,如果是这种情况交换它们。 第二:增加低值

当低电平不低于高电平(阵列大小)时停止。

参见选择排序的定义:

http://en.wikipedia.org/wiki/Selection_sort

答案 2 :(得分:0)

对于寻找另一种使用递归进行选择排序的方法的人来说,这是一种方法。

//the method that will be called to sort the array recursively
public static void selectionSort(double[] arr) {
    selectionSort(arr, 0);
}

//this is a recursive helper method.
//arr is the array to be sorted and index is the current index in
//the array which will be swapped with the smallest value in the
//remaining part of the array
private static void selectionSort(double[] arr, int index) {
    //if index has reached the second to last value, there are
    //no more values to be swapped
    if (index < arr.length - 1) {
        //let index, at first, be the index at which the smallest element is located
        int smallestIndex = index;
        //find the smallest entry in the array from i=index to i=index.length - 1
        for (int i = index + 1; i < arr.length; i++) {
            //if the element at i is smaller than the element at smallestIndex, then update the value of smallestIndex
            if (arr[i] < arr[smallestIndex]) {
                smallestIndex = i;
            }
        }
        //swap the elements of arr[smallestIndex] and arr[index]
        double t = arr[index];
        arr[index] = arr[smallestIndex];
        arr[smallestIndex] = t;
        selectionSort(arr, index + 1);
    }
}