我正在使用Merge Sort中的递归来研究控制流。
我使用的特定算法是:
MergeS(ar, p, r){
1. if p<r{
2. k = floor[(p+r)/2]
3. MergeS(ar, p , k)
4. MergeS(ar, k+1, r) //in the schematic diagram I have written this as mergeS(,,)
5. Merge(ar, p ,k, r)
6. }
7.}
Merge(ar, p, k, r){
8. n1 = k-p+1
9. n2 = r-p
10. let L[1...n1+1] and R[1....n2+1] be new arrays
11. for i=1 to n1
12. L[i] = ar[p+i-1]
13. for j=1 to n2
14. R[j] = ar[k+j]
15. L[n1+1] = Infinity
16. R[n2+1] = Infinity
17. i = 1
18. j = 1
19. for t = p to r
20. if L[i] <= R[j]
21. A[t] = L[i]
22. i = i+1
23. else
24. A[t] = R[j]
25. j = j+1
30. }
MergeS(ar, k+1, r)
与merge(ar, k+1, r)
完全相同。我在后者中使用了小写m
,只是为了在原理图中更好的视觉清晰度。
为了理解目的,我采用了一个数组示例 - 43,32,56,12,4 。
递归调用的流程如下所示,直到第一次调用Merge并执行该块内的代码为止。
--- 1: MergeS(ar,0,5) -----
if(0<5):true ; set k=(0+5)/2
---暂停1: MergeS(ar,0,5) -----调用 - &gt; 2: MergeS(ar,0,2) ---------
if(0<2):true ; set k=(0+2)/2
---暂停2: MergeS(ar,0,2) -----调用 - &gt; 3: MergeS(ar,0,1) ---------
if(0<1):true ; set k=(0+1)/2
---暂停3: MergeS(ar,0,1) -----调用 - &gt; 4: MergeS(ar,0,0) ---------
if(0<0):false
---恢复3:合并(ar,0,1) -----呼叫 - &gt; 5:合并(ar,0 + 1,5)< /强> ---------
if(1<5):true ; set k=(1+5)/2
---暂停5:合并(ar,0 + 1,5) -----调用 - &gt; 6: MergeS(ar,1,3)< /强> ---------
if(1<3):true ; set k=(1+3)/2
---暂停6: MergeS(ar,1,3) -----调用 - &gt; 7: MergeS(ar,1,2) ---------
if(1<2):true ; set k=(1+2)/2
---暂停7: MergeS(ar,1,2) -----调用 - &gt; 8: MergeS(ar,1,1) ---------
if(1<1):false
---简历7:合并(ar,1,2) ------通话 - &gt; 9:合并(ar,1 + 1,5) ---------
if(2<5):true ; set k=(2+5)/2
---暂停9:合并(ar,2,5) --------调用 - &gt; 10:合并(ar,2,3) ---------
if(2<3):true ; set k=(2+3)/2
---暂停10:合并(ar,2,3) -------调用 - &gt; 11:合并(ar,2,2)< /强> ----------
if(2<2):false
---恢复10:合并(ar,2,3) -----呼叫 - &gt; 12:合并(ar,2 + 1,5)< /强> ----------
if(3<5):true ; set k=(3+5)/2
---暂停12:合并(ar,2 + 1,5) ------通话 - &gt; 13:合并(ar,5,5) ---------
if(5<5):false
---简历12:合并(ar,2 + 1,5) -------调用 - &gt; 合并(ar,3,4,5) ) ----------
n1 = 4-3+1=2
n2 = 5-4=1
for(i = 0 to i=1):
iteration1:
L[0] = ar[3+0-1]= ar[2] //value 56 is assigned to ar[2]
iteration2:
L[1] = ar[3+1-1] = ar[3] //value 12 is assigned to ar[3]
for(j=0 to j=0):
iteration1:
R[0] = ar[4+0] = ar[4] //value 4 is assigned to ar[4]
x = 0;
y = 0;
for(t=0 to t=1):
iteration1:
/* if(L[0]<= R[0]) //56<=4:false */
else
ar[0] = R[0] //4 is assigned to ar[0]
y = y+1
iteration2:
if(L[0]<=R[1]): //56<=infinity
ar[1] = L[0] // 56 is assigned to ar[1]
在上一步之后,我在4
中获得了值ar[0]
,在56
中获得了值ar[2]
。我猜这是错的。
我需要帮助了解我出错的地方以及对此的解释。
答案 0 :(得分:0)
问题中算法中的索引需要在代码中修改以便更简单地使用。我不是说算法错了,它绝对正确,只需要修改。
Merge
的调整代码:
private static void Merge(int[] ar, int p, int k, int r) {
int n1 = k-p+1;
int n2 = r-k;
int[] L = new int[n1+1];
int[] R = new int[n2+1];
for(int i=0; i<n1; i++){
L[i] = ar[p+i]; // p+i and not p+i-1
}
for(int i=0; i<n2; i++){
R[i] = ar[k+i+1]; //k+1+i and not k+i
}
// Use of Tnteger.MAX_VALUE
L[n1]=Integer.MAX_VALUE;
R[n2]=Integer.MAX_VALUE;
int i = 0;
int j = 0;
for(int t=p; t<=r; t++){ //carefully set initialization and t<=r and not simply t<r
if(L[i]<r[j]){
ar[t] = L[i];
i++;
}
else{
ar[t] = R[j];
j++;
}
}
}
}
正确的递归调用流程如下所示:(上述控制图流程的变化是斜体)
--- 1: MergeS(ar,0,5) -----
if(0<5):true ; set k=(0+5)/2
---暂停1: MergeS(ar,0,5) -----调用 - &gt; 2: MergeS(ar,0,2) ---------
if(0<2):true ; set k=(0+2)/2
---暂停2: MergeS(ar,0,2) -----调用 - &gt; 3: MergeS(ar,0,1) ---------
if(0<1):true ; set k=(0+1)/2
---暂停3: MergeS(ar,0,1) -----调用 - &gt; 4: MergeS(ar,0,0) ---------
if(0<0):false
--- Break 4: MergeS(ar,0,0) ----- Call - &gt; 5: mergeS(ar, 0 + 1, 1 ) ---------
if(1<_1_):_false_ ;
--- 中断5:合并(ar,0 + 1,1) -----调用 - &gt;合并(ar,0,0,1)< / em>的
执行带参数Merge
的{{1}}函数后,交换数组 ar, 0, 0, 1
的前两个索引处的元素。
维护一堆函数调用非常方便。