在这个特定的代码中...
findMinIndex 将给定索引中的元素与它前面的所有元素(具有更高索引的元素)进行比较,直到数组的最后一个元素。
所以如果你有一个数组:
int[] a = { 7, 4, 2, 6 };
然后你调用findMinIndex(a, 0);,它会首先检查索引0 之后是否有一个元素。这就是这部分的作用index == data.length - 1。如果后面没有元素,它将简单地返回它传递的index。但显然在索引 0 之后有一个元素,因为数组的长度为 4。
现在我们已经确认index 之后有元素,是时候获取index 之后的smallest 元素的索引了。这样,我们可以将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
这个函数也使用递归。 swap 方法是不言自明的(它在 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
结束。
与递归相比,使用循环更容易理解选择排序。