我有这个方法,我从一个关于选择排序的网站,我需要检查它的工作原理:
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得到数组的最后一个索引?怎么样?
答案 0 :(得分:3)
在此特定代码中......
findMinIndex
将给定索引中的元素与其前面的所有元素(具有更高索引的元素)进行比较,直到数组的最后一个元素。
所以如果你有一个数组:
int[] a = { 7, 4, 2, 6 };
并且你调用findMinIndex(a, 0);
它将首先检查索引0后面是否有一个元素。这就是这部分index == data.length - 1
的作用。如果之后没有元素,它将只返回它传递的index
。但是由于数组长度为4,因此在索引0之后显然有一个元素。
现在我们已经确认在index
之后有元素,现在是时候在index
之后得到最小元素的索引了。通过这种方式,我们可以将index
处的元素与其前面的所有元素进行比较,以查看index
到array.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)是否更低,如果是这种情况交换它们。 第二:增加低值
当低电平不低于高电平(阵列大小)时停止。
参见选择排序的定义:
答案 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);
}
}