簡體   English   中英

替代基於遞歸的合並排序邏輯

[英]alternative to recursion based merge sort logic

這是python中的合並排序邏輯:(這是第一部分,忽略函數merge())問題點是將遞歸邏輯轉換為while循環。 代碼禮貌: Rosettacode Merge Sort

def merge_sort(m):
    if len(m) <= 1:
        return m

    middle = len(m) / 2
    left = m[:middle]
    right = m[middle:]

    left = merge_sort(left)
    right = merge_sort(right)
    return list(merge(left, right))

是否有可能在while循環中使它成為一種動態,而每個左右數組都分成兩個,一種指針根據左右數組的數量不斷增加並打破它們直到只剩下單個長度的列表? 因為每當下一次分割進入左右兩側時,陣列就會不斷分解,直到只剩下單個長度列表,因此左側(左 - 左,右 - 右)和右側(右 ​​- 左,右 - 右)中斷將增加,直到達到所有大小為1的列表。

一種可能的實現可能是這樣的:

def merge_sort(m):
    l = [[x] for x in m]                  # split each element to its own list
    while len(l) > 1:                     # while there's merging to be done 
        for x in range(len(l) >> 1):      # take the first len/2 lists
            l[x] = merge(l[x], l.pop())   # and merge with the last len/2 lists
    return l[0] if len(l) else []

遞歸版本中的堆棧幀用於存儲需要合並的逐漸變小的列表。 您正確地識別出在堆棧的底部,無論您要排序的是什么,每個元素都有一個單元素列表。 因此,通過從一系列單元素列表開始,我們可以迭代地構建更大的合並列表,直到我們有一個單獨的排序列表。

根據讀者的要求,從替代方法轉換為基於遞歸的合並排序邏輯

消除遞歸的一種方法是使用隊列來管理未完成的工作。 例如,使用內置的collections.deque

from collections import deque
from heapq import merge

def merge_sorted(iterable):
    """Return a list consisting of the sorted elements of 'iterable'."""
    queue = deque([i] for i in iterable)
    if not queue:
        return []
    while len(queue) > 1:
        queue.append(list(merge(queue.popleft(), queue.popleft())))
    return queue[0]

據說 ,每個遞歸函數都可以以非遞歸的方式編寫,所以簡短的答案是:是的,它是可能的。 我能想到的唯一解決方案是使用基於堆棧的方法。 當遞歸函數調用自身時,它會在內部堆棧上放置一些上下文(其參數和返回地址),這對您來說是不可用的。 基本上,為了消除遞歸,你需要做的就是編寫自己的堆棧,每次進行遞歸調用時,都要將參數放到這個堆棧中。

有關更多信息,您可以閱讀本文 ,或參考Robert Lafore的“Java中的數據結構和算法”中的“消除遞歸”一節(雖然本書中的所有示例都是用Java語言提供的,但很容易掌握主要內容。理念)。

與Dan的解決方案一起使用並接受關於pop的建議,我仍嘗試消除while和其他不那么pythonic的方法。 這是我建議的解決方案:PS:l = len

我對Dans解決方案的疑問是,如果L.pop()和L [x]相同並且產生沖突,就像在迭代超過L長度的一半之后的奇數范圍的情況一樣?

def merge_sort(m):
    L = [[x] for x in m]  # split each element to its own list
    for x in xrange(l(L)):      
        if x > 0:
            L[x] = merge(L[x-1], L[x])
    return L[-1]

這可以繼續進行所有的學術討論,但我得到了一個替代遞歸方法的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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