簡體   English   中英

關於歸並排序中的遞歸 function

[英]About recursive function in merge sort

我試圖逐步理解由遞歸 function 實現的合並排序算法的一步一步(所有事情和每一個小細節)。 但是,我真的不明白下面的 function 發生了什么,這是我從 Geeks for geeks 中找到的。 據我所知,遞歸 function 被遞歸調用,直到達到基本情況並返回給調用者。 但是,在這個 function 中,我仍然想到以下問題:

  1. 這里的基本情況是什么?
  2. 在遞歸調用到達基本情況之后(在這種情況下,我認為mergesort(singledigit),我們不應該返回一些東西嗎?我真的不知道我應該問什么樣的問題,因為遞歸的整個想法令人困惑我。請幫忙。例如,我目前的理解是,讓 arr=[4,2,7,9,12,3,1,5] 然后遞歸調用將按 ff 順序進行 merge(arr)->merge([ 4,2,7,9])->merge([4,2])->merge([4]) 但由於 len(4)<=1,它沒有進入 ff 的 if 子句function,這意味着它確實 go 超過了 mergesort() 的兩行 function 調用。然后它肯定會繼續進行排序,最后不會是一樣的,我會這樣做。誤解了執行的流程。所以如果有人可以通過示例 go(如使用上面的數組)來解釋執行的步驟,我將不勝感激。謝謝你前進。
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分成兩半后, LR ,我們知道兩者的大小都比原始數組arr小。 因此我們“知道”在調用mergeSort(L)之后, L現在已排序。 同樣對於R

不平凡的步驟是合並。 假設LRwhile循環之前已經排序,很容易看出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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM