通过Merge Sort

时间:2017-01-08 18:08:45

标签: algorithm sorting recursion merge

我正在使用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]。我猜这是错的。

我需要帮助了解我出错的地方以及对此的解释。

1 个答案:

答案 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 的前两个索引处的元素。

维护一堆函数调用非常方便。