[英]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.