[英]About recursive function in merge sort
我試圖逐步理解由遞歸 function 實現的合並排序算法的一步一步(所有事情和每一個小細節)。 但是,我真的不明白下面的 function 發生了什么,這是我從 Geeks for geeks 中找到的。 據我所知,遞歸 function 被遞歸調用,直到達到基本情況並返回給調用者。 但是,在這個 function 中,我仍然想到以下問題:
def mergeSort(arr):
if len(arr) > 1:
# print("This is funny to be honest",arr[0],len(arr))
mid = len(arr)//2
print("This is funny",arr,arr[0],len(arr))
L = arr[:mid]
R = arr[mid:]
mergeSort(L)
mergeSort(R)
i = j = k = 0
while i < len(L) and j < len(R):
if L[i] < R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1
# Checking if any element was left
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
除了遞歸的 function 將 arrays 拆分為兩個子數組並調用自身,直到生成兩個大小為 1 的子數組,什么都沒有發生。 此時,這些子數組被合並以創建大小為 2 的排序運行。然后排序遵循調用鏈上下,深度優先,左優先,合並大小不斷增加的運行,直到它到達初始調用其中兩個排序的運行被合並回原始數組。
請注意,自上而下的合並排序主要是學術性的。 大多數庫將穩定排序實現為插入排序和自底向上合並排序的混合體,例如 Timsort。
mergeSort(arr)
不返回任何值。 它只是返回。 但它確實改變了它的參數數組arr
。 看到所有這些arr[k] =...
語句了嗎? 這就是他們正在做的事情,將新元素一個一個地放入數組的條目中。
現在您想了解 function 調用的整個鏈,但這很難。 我們精確地使用遞歸,因此我們不必這樣做,而是可以輕松解決我們的問題。
理解遞歸 function 的方法首先是假設它工作正常。
這意味着我們可以在需要解決它所期望的問題時使用它。
這似乎是循環的。 畢竟def solve(x): { solve(x) }
讓我們無處可去。
訣竅是使用我們的 function 來解決我們原始問題的較小子問題。 我們已經“知道”它可以正常工作。 我們只需要以某種方式組合已解決的子問題,以便我們的原始問題得到解決。 這是不平凡的一步。
具體來說,將數組arr
分成兩半后, L
和R
,我們知道兩者的大小都比原始數組arr
小。 因此我們“知道”在調用mergeSort(L)
之后, L
現在已排序。 同樣對於R
。
不平凡的步驟是合並。 假設L
和R
在while
循環之前已經排序,很容易看出arr
將在while
循環完成后按排序順序填充其原始元素。
就是這樣。
或者是嗎? 好吧,我們有基本情況要考慮,數組arr
太小以至於不能分成兩半。 不過這沒問題,因為這樣的數組已經排序。
因此,該假設適用於最小尺寸 arrays,它也適用於更大的 arrays,因為在我們的 function 正確適用於較小尺寸的假設下,合並工作正常。
因此,它適用於我們的輸入數組,無論它的大小是多少。
換句話說,它適用於任何數組。 因此,它適用於所有人。
這被稱為“歸納”: A. 我們證明一個性質對於基本情況成立; B. 我們證明組合步驟保留了該屬性; 因此 C。 該屬性適用於任何更大的情況,我們通過結合為其較小的子問題找到的解決方案來解決這些問題,這些子問題在性質上與原始問題相似:
solve(X --> R) : isBase(X) --> R = X.
solve(X+Y --> R) : solve(X --> A),
solve(Y --> B),
combine( (A,B) --> R ).
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.