知道为什么我的Stack合并排序不起作用?它与我对数组的merge-sort非常相似,但是那个有效。我的递归设置错了吗?
谢谢!
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]
答案 0 :(得分:2)
我假设你这样做是为了学习合并排序或LIFO,但如果没有,因为你的stack
只是一个python列表(数组),函数sorted(s._data)
或s._data.sort()
都是完成你需要的。如果你需要继续堆栈那么......
首先,调试:
如果您想了解错误,可以放置一些print()
语句,以便在代码的每个阶段查看堆栈的外观。您的排序功能很好,并且可以正确地分离您的阵列。该缺陷在合并部分。算法的合并部分发生在使用3 while循环的部分递归调用sort()
之后。最后,通过示例输入,将合并这些数组:
MERGING
L [19]
R [11, -4]
由于您使用堆栈LIFO执行此操作,因此基于此条件pop()
使用left.top() < right.top()
,生成的新堆栈数组变为:
[19, -4, 11]
。 Last in,First,out,表示一旦Left数组为空,就会添加第二个,因为Right被清空。但是,通过适当的合并,此数组将被合并排序,并且应该合并为:
[-4, 11, 19]
您的下一次合并是:
MERGING
L [8, 0]
R [19, -4, 11]
这导致新堆栈为:[11, 0, 8, -4, 19]
,最终导致19被添加到最终堆栈中,因此19在结果中位于索引0的位置,您得到:{{ 1}}
解决:强>
要解决此问题,您应该使用[19, 14, 1, 21, 3, 14, -4, 8, 0, 11]
代替FIFO,并且始终将最小的数字添加到队列中,该队列将位于数组的索引0处(即从左侧移动)到右)。如果您绝对必须使用queue
并继续使用stack
和append
方法,那么,我建议:
首先,在合并部分中,合并较小的数字,优先级高于较高的数字。然后,在从左侧或右侧数组添加到合并部分中的堆栈之前,您需要确保要添加的数字大于堆栈的当前头部(Last in)。如果它不是更大,那么你需要将.pop()
堆栈放入一个新数组或左/右数组(你没有使用哪个数组),直到下一个添加的值实际上大于堆栈的头部。然后,继续使用相同的方法,只向堆栈添加大于堆栈头部的值,记住将pop'd值也按正确的顺序添加回堆栈。
代码更新解决方案
以下是添加的代码作为维护堆栈方法的解决方案:
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())