以下代码片段来自Robert SedgeWick和Kevin Wayne的Algorithms一书。
public class MergeBU {
// This class should not be instantiated.
private MergeBU() { }
// stably merge a[lo..mid] with a[mid+1..hi] using aux[lo..hi]
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
// copy to aux[]
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
// merge back to a[]
int i = lo, j = mid+1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++]; // this copying is unneccessary
else if (j > hi) a[k] = aux[i++];
else if (less(aux[j], aux[i])) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
/**
* Rearranges the array in ascending order, using the natural order.
* @param a the array to be sorted
*/
public static void sort(Comparable[] a) {
int n = a.length;
Comparable[] aux = new Comparable[n];
for (int len = 1; len < n; len *= 2) {
for (int lo = 0; lo < n-len; lo += len+len) {
int mid = lo+len-1;
int hi = Math.min(lo+len+len-1, n-1);
merge(a, aux, lo, mid, hi);
}
}
assert isSorted(a);
}
//other methods
}
我的问题是关于sort方法的内部for循环条件。
如果输入数组有10个元素,则对长度为4的子数组进行合并的数组上的传递将保留最后两个元素,这些元素相对于彼此排序但不与其他元素相关
在下一次传递中,合并的子数组的长度变为8,并且它仍然会使最后两个元素相对于其他元素保持未合并。这是长度为10的数组的最后一次传递。
因此,最后两个元素相对于数组中的其他元素保持未分类,因为lo&lt; n-len检查。本节并未说明数组中元素的数量应该是2的幂。这是勘误还是我遗漏了什么?
我肯定会忽略一些东西,因为以下测试代码正确地对我的10个元素数组进行排序。
public static void main(String[] args) {
Integer[] array = {1,2,3,4,5,6,7,8,-50, -80};
MergeBU.sort(array);
System.out.println(Arrays.toString(array));
}
有人可以帮我解决。
答案 0 :(得分:2)
您的分析不正确。合并进行如下。
在len = 4
的传递中,它将合并两个子阵列[0-3]
和[4-7]
。你是正确的,最后两个项目没有合并。
len = 8
时,它会合并两个子阵列[0-7]
和[8-9]
。
我怀疑你在循环控制变量增加时会误解。您应该在调试器中单步执行sort
方法,并注意两个循环中lo
和len
的值。
顺便说一句,合并排序的定义中没有任何内容要求长度为2的幂。但是,处理不是2的幂的数组会增加一些复杂性。这就是if (i > mid)
循环中if (j > hi
和merge
}条件的原因。