在创建此测试代码时,我使用了来自Wikipedia的自上而下的伪代码:
public static void main(String args[]) {
int[] nums = new int[] { 17, 5, 3, 7, 6, 3, 11, 2 };
mergeSort(nums);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ,");
}
}
public static void mergeSort(int[] A) {
int[] B = new int[A.length];
System.arraycopy(A, 0, B, 0, A.length);
splitMerge(B, 0, A.length, A); // sort data from B[] into A[]
}
public static void splitMerge(int[] B, int begin, int end, int[] A) {
if (end - begin < 2)
return;
int middle = (end + begin) / 2;
splitMerge(B, begin, middle, A);
splitMerge(B, middle, end, A);
System.out.println("begin: " + begin + " mid: " + ((end - begin)/2) + " end: " + end + " SIZE: " + (end-begin));
merge(B, begin, middle, end, A);
}
public static void merge(int[] B, int begin, int middle, int end, int[] A) {
int i = begin;
int j = middle;
for (int k = begin; k < end; k++) {
if (i < middle && (j >= end || B[i] <= B[j])) {
A[k] = B[i];
i = i + 1;
} else {
A[k] = B[j];
j = j + 1;
}
}
}
这应该或多或少与伪代码完全相同,那为什么它不起作用? 这是输出:
begin: 0 mid: 1 end: 2 SIZE: 2
begin: 2 mid: 1 end: 4 SIZE: 2
begin: 0 mid: 2 end: 4 SIZE: 4
begin: 4 mid: 1 end: 6 SIZE: 2
begin: 6 mid: 1 end: 8 SIZE: 2
begin: 4 mid: 2 end: 8 SIZE: 4
begin: 0 mid: 4 end: 8 SIZE: 8
6 ,3 ,11 ,2 ,17 ,5 ,3 ,7 ,
答案 0 :(得分:0)
当您更改原始B
数组时,您的A
数组包含原始数组的副本,并且您永远不会更改它。
这意味着merge
方法无法工作,因为它合并了两个未排序的数组(两个B
子数组,在整个算法中保持未排序)。
为了正确执行merge
,您应该将begin
到end
的索引从A
数组复制到B
数组在合并方法的开始。
您只需添加声明
即可System.arraycopy(A, begin, B, begin, end - begin);
作为merge
方法的第一个陈述。
即:
public static void merge(int[] B, int begin, int middle, int end, int[] A) {
System.arraycopy(A, begin, B, begin, end - begin);
int i = begin;
int j = middle;
for (int k = begin; k < end; k++) {
if (i < middle && (j >= end || B[i] <= B[j])) {
A[k] = B[i];
i = i + 1;
} else {
A[k] = B[j];
j = j + 1;
}
}
}
这将产生输出
2 ,3 ,3 ,5 ,6 ,7 ,11 ,17 ,
用于给定的输入。