[英]How do multiple recursive calls execute in merge sort?
在了解合並排序的工作原理后,我在實現方面遇到了問題:
我從main調用了這個方法:
void sort(int arr[], int beg, int end)
{
if (beg<end)
{
int mid = (beg+end)/2;
sort(arr, beg, mid); //call a
sort(arr , mid+1, end); //call b
merge(arr, beg, mid, end);
}
}
2 個遞歸調用如何執行?
第一個是每次更改開始和結束值,當第一個遞歸調用停止執行時 (end>beg) 第二個是從最后修改的值還是初始值開始?
我看不出它會如何從最初的開始,而從最后的開始對我來說沒有意義。
假設你有一個長度為 5 的array
,比如arr[] = {3,5,4,1,2}
那么第一次sort(arr,0,5)
之后的后續遞歸調用將是
CALL#1: sort(a,0,2) CALL#2: sort(a,0,1) CALL#3: sort(a,0,0) CALL#3: sort(a,1,1) CALL#2: sort(a,2,2) CALL#1: sort(a,3,5) CALL#4: sort(a,3,4) CALL#5: sort(a,3,3) CALL#5: sort(a,4,4) CALL#4: sort(a,5,5)
當啟動新的遞歸調用時,當前變量值存儲在堆棧中,並使用新值調用方法。 然后它使用這些新值執行這個新調用。 返回此調用后,它會從堆棧中選取值並繼續使用舊值。
簡而言之,當函數被調用時,它的所有局部變量都在stack
上創建(即堆棧指針按使用的局部變量數量遞增)。 函數退出時,堆棧指針遞減相同的數量。
考慮下面的例子,帶有一些局部變量字節的函數foo()
調用帶有一些其他局部變量字節的bar()
。 (為了簡單起見,我從堆棧中排除了函數返回地址,函數沒有參數)
/*stack growth in this direction ---->*/
foo()-------+
|
/*foo code execution */
|
bar()----------+
|
/* bar() Code execution */
|
+------------+
|
|------------+
由於函數被調用,堆棧被擴展並在函數退出時收縮。
在遞歸函數的情況下, bar()
恰好是foo()
一次又一次。 但是在每個函數調用的新堆棧位置上。
2 個遞歸調用如何執行?
在您的情況下,函數sort
遞歸調用將創建beg
並在不同的堆棧位置end
,並且不會沖突或改變先前函數調用的局部變量。
當第一個遞歸調用停止執行 (end>beg) 時,第二個遞歸調用是從最后修改的值還是從初始值開始?
第一個遞歸調用在條件(end>=beg)
上退出
考慮下面的例子來理解第一次遞歸調用何時退出,
int a[] = {1,2,3,4,5};
sort(a,0,4)------>+
|
sort(a,0,2)------>+
|
sort(a,0,1)----->+
|
sort(a,0,0)----->+
|
//0< 0
|
|<----------+
|
sort(a,1,1)---->+
|
//1< 1
|
|<----------+
|
merge(a, 0, 0, 1)
|
|<----------+
|
sort(a,2,2)----->+
|
//2 < 2
|
|<----------+
|
merge(a, 0, 1, 2)
|
|<----------+
|
sort(a,3,4)------>+
|
sort(a,3,3)----->+
|
//3 < 3
|
|<----------+
|
sort(a,4,4)----->+
|
//4 < 4
|
|<----------+
|
merge(a, 3, 3, 4)
|
|<----------+
|
merge(a, 0, 2, 4)
|
|<------------------+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.