簡體   English   中英

合並合並排序

[英]Merge-sort for Stacks

知道為什么我的Stack合並排序不起作用嗎? 這與我對數組的合並排序完全相同,但是可以工作。 我的遞歸設置錯誤嗎?

謝謝!

def sort(stack):
    if len(stack) > 1:
        middle = len(stack) // 2
        stack_len = len(stack)
        left = Stack()
        right = Stack()
        for i in range(middle):
            left.push(stack.pop())
        for i in range(middle, stack_len):
            right.push(stack.pop())
        sort(left)
        sort(right)
        while(not left.is_empty() and not right.is_empty()):
            if (left.top() < right.top()):
                stack.push(right.pop())
            else:
                stack.push(left.pop())
        while(not left.is_empty()):
            stack.push(left.pop())
        while(not right.is_empty()):
            stack.push(right.pop())

這是我的Stack ADT實現:

class Stack:

    def __init__(self):
        self._data = []

    def __len__(self):
        return len(self._data)

    def is_empty(self):
        return len(self) == 0

    def push(self, i):
        self._data.append(i)

    def pop(self):
        if not self.is_empty():
           return self._data.pop()
        raise IndexError('Cannot pop an empty Stack.')

    def top(self):
        if not self.is_empty():
            return self._data[len(self) - 1]
        raise IndexError('Cannot check the top of an empty Stack.')

我的測試用例是:

if __name__ == '__main__':
    s = Stack()
    s.push(8)
    s.push(0)
    s.push(-4)
    s.push(11)
    s.push(19)
    s.push(21)
    s.push(3)
    s.push(14)
    s.push(1)
    s.push(14)
    print(s._data)
    sort(s)
    print(s._data)

這使:

[8, 0, -4, 11, 19, 21, 3, 14, 1, 14]

[19, 14, 1, 21, 3, 14, -4, 8, 0, 11]

我假設您正在執行此操作以學習合並排序或LIFO,但是如果不是這樣,由於您的stack只是一個python列表(數組),因此sorted(s._data)s._data.sort()函數都s._data.sort()您的需要。 如果您需要繼續堆棧,則...

首先,調試:

如果要了解錯誤,可以放置一些print()語句以查看代碼每個階段的堆棧外觀。 您的排序功能很好,並且可以正確分隔數組。 缺陷在於合並部分。 算法的合並部分在使用3個while循環對部分中的sort()進行遞歸調用后發生。 使用示例輸入,最終,這些數組將合並:

MERGING
L [19]
R [11, -4]

由於您使用堆棧LIFO進行此操作,因此基於以下條件使用pop()left.top() < right.top() ,結果新的堆棧數組變為: [19, -4, 11] left.top() < right.top() [19, -4, 11] 后進先出,表示一旦Left數組為空,則第二個添加-4,因為Right被清空。 但是,如果進行適當的合並,則此數組將按排序方式進行合並,並且應該像這樣合並:

[-4, 11, 19]

您的下一個合並是這樣的:

MERGING
L [8, 0]
R [19, -4, 11]

結果導致新堆棧為: [11, 0, 8, -4, 19] ,最終導致將19首先添加到最終堆棧中,因此19在結果中位於索引0的位置,您得到這: [19, 14, 1, 21, 3, 14, -4, 8, 0, 11]

解析度:

為了解決這個問題,您應該改用一個queue ,該queue將是FIFO,並且始終將最低的數字首先添加到隊列中,該隊列將在數組的索引0處(即,從左向右移動)。 如果您絕對必須使用stack並繼續執行append.pop()方法,那么,我建議:

首先,在合並部分中,將優先級較高的較小數字與優先編號較高的數字合並。 然后,在合並部分中從Left或Right數組添加到堆棧之前,需要確保要添加的數字大於堆棧的當前頭(Last in)。 如果不大,則需要將堆棧pop()到一個新數組或左/右數組(無論您不在使用的那個數組),直到下一個增加的值實際上大於堆棧的頭部。 然后,繼續使用相同的方法,僅向堆棧中添加大於堆棧頭的值,並記住以正確的順序將彈出的值添加回堆棧中。

代碼更新解決方案

這是添加的代碼,作為維護堆棧方法的解決方案:

while(not left.is_empty() and not right.is_empty()):
    if (left.top() > right.top()):
        if stack.is_empty() or stack.top() <= right.top():
            stack.push(right.pop())
        else:
            left.push(stack.pop())
    else:
        if stack.is_empty() or stack.top() <= left.top():
            stack.push(left.pop())
        else:
            right.push(stack.pop())
while(not left.is_empty()):
    if stack.is_empty() or stack.top() <= left.top():
        stack.push(left.pop())
    else:
        right.push(stack.pop())
while(not right.is_empty()):
    if stack.is_empty() or stack.top() <= right.top():
        stack.push(right.pop())
    else:
        left.push(stack.pop())
while(not left.is_empty()):
    stack.push(left.pop())

更新的解決方案: [-4, 0, 1, 3, 8, 11, 14, 14, 19, 21]

暫無
暫無

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

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