我在理解合并排序算法的'merge'部分时遇到了一些麻烦,因为我试图在上下文中理解算法的某些部分,并且某些变量/循环没有意义我。我理解递归除法过程和合并的排序方面,但在这个特定的合并算法中:
public static void merge(int data[], int temp[], int low, int middle, int high){
int ri=0; //result index
int ti=low;//temp index
int di=middle;//data index
int[] result = new int[high-low+1];
while (ti<middle && di<=high){
if (data[di]<temp[ti]){
result[ri++] = data[di++];//smaller is in data
}
else{
result[ri++] = temp[ti++];//smaller is in temp
}
}
while(ti<middle) result[ri++]=temp[ti++];
while(di<=high) result[ri++]=data[di++];
for(int i=0;i<high;i++) data[low+i]=result[i];
我不明白最后3个循环:
while(ti<middle) result[ri++]=temp[ti++];
while(di<=high) result[ri++]=data[di++];
for(int i=0;i<high;i++) data[low+i]=result[i];
你能解释一下这三个循环在合并的上下文中是什么,还有什么进一步的建议可以更好地理解合并排序算法的合并部分?
答案 0 :(得分:1)
此循环while (ti<middle && di<=high)
的条件意味着一旦在两半中的至少一半中没有更多元素,它就会终止。但是在另一个元素中仍然可以存在一些元素。这就是为什么我们需要这两行:
while(ti<middle) result[ri++]=temp[ti++]; // Remaining elements from the first half.
while(di<=high) result[ri++]=data[di++]; // Remaining elements from the second half.
现在我们需要将合并的结果复制到原始数组。这正是最后一行所做的。
关于合并阶段的理解:您是否了解算法本身(在数学意义上,没有引用任何具体的编程语言)?如果你没有,那么首先要完全理解它,而不是查看任何代码。如果您确实理解算法但不了解此代码,那很好,因为这段代码非常糟糕。
您可以看一下更清晰的实现:
mergeSort [] = []
mergeSort [x] = [x]
mergeSort xs =
let (firstHalf, secondHalf) = splitAt (length xs `div` 2) xs
in merge (mergeSort firstHalf) (mergeSort secondHalf)
merge xs [] = xs
merge [] ys = ys
merge xs@(x:xt) ys@(y:yt)
| x <= y = x : merge xt ys
| otherwise = y : merge xs yt