在Python中反转堆栈

时间:2015-10-06 16:48:19

标签: python stack

要反转堆栈:

  1. 我做了一个空的临时堆栈
  2. 我使用了tempstack.push(stack.pop())
  3. 然后将其重命名为stack = tempstack
  4. 但它似乎不起作用。知道为什么吗?

    要拨打此电话,我只想使用reverse(stack),而不是stack = reverse(stack)

    def reverse(stack):
        new_stack = Stack()
        while not stack.is_empty():
            new_stack.push(stack.pop())
        stack = new_stack
    

7 个答案:

答案 0 :(得分:3)

如果您正在使用实际list来实现堆栈(即Stack继承自list或基本 列表) ,然后简单地反转list就地:

def reverse_stack(stack):
    stack.reverse()

为了避免混淆,我将函数重命名为reverse_stack;你可以仍称它为reverse。例如:

>>> stack = [1, 2, 3]
>>> reverse_stack(stack)
>>> stack
[3, 2, 1]

但是,您的Stack课程似乎并未从list继承,而是将基础list保留在私有属性中,因此您无法直接使用MutableSequence上的任何Stack API。因此,

版本2,仅使用is_empty

pushpopStack方法

仅使用 Stack,而不是list s或deque等等。首先,有几个辅助函数:

def reverse_copy_stack(stack, rev_stack=None):
    '''Return a reversed copy of stack, which is emptied.
    rev_stack receives the reversed copy if it's not None
    '''
    if rev_stack is None:
        rev_stack = Stack()
    while not stack.is_empty():
        rev_stack.push(stack.pop())
    return rev_stack

def copy_stack(stack):
    '''Return a copy of stack, which is emptied.'''
    return reverse_copy_stack( reverse_copy_stack(stack))

现在我们可以实施reverse_stack

def reverse_stack(stack):
    '''Reverse stack in-place'''
    new_stack = copy_stack(stack)
    # Empty stack
    while not stack.is_empty():
        stack.pop()
    # put reversed copy of new_stack in stack
    reverse_copy_stack(new_stack, stack)

答案 1 :(得分:1)

添加返回值

def reverse(stack):
    new_stack = Stack()
    while not stack.is_empty():
        new_stack.push(stack.pop())
    return new_stack

并在调用函数时执行此操作:

stack = reverse(stack)

您正在为函数内部的堆栈赋值,但不是从您调用它的位置。范围问题。

答案 2 :(得分:1)

正如其他人指出的那样,最后的任务没有做任何事情。但是,这里练习背后的想法可能只是使用标准堆栈原语pushpopis_empty,而不依赖于确切的堆栈实现来使用{{1等等。

要注意的关键点是堆栈是一个后进先出结构,因此读取其内容会自动以相反的顺序生成它们。这就是为什么使用另一个堆栈进行临时存储的解决方案不起作用的原因:

list.reverse

这里堆栈内容反转两次:一次从原始堆栈中读取它们,一次从临时堆栈中读取它们,所以最终得到原始顺序的堆栈内容。要实际反转堆栈,您需要将项目提取到列表中,然后按顺序遍历(从开始到结束),在原始堆栈上推送项目:

def reverse(stack):
    # Doesn't work
    temp = Stack()
    while not stack.is_empty():
        temp.push(stack.pop())
    while not temp.is_empty():
        stack.push(temp.pop())

编辑:受BrianO的回答启发,这是一个根本不使用列表的版本(但实例化两个临时堆栈):

def reverse(stack):
    items = []
    while not stack.is_empty():
        items.append(stack.pop())
    for item in items:
        stack.push(item)

这里的想法是利用复制堆栈确实反转内容的事实 - 只是复制它返回再次反转它。所以我们只复制它三次,首先从原始堆栈复制到临时堆栈,然后从临时堆栈复制到另一个临时堆栈,最后从另一个临时堆栈复制到原始堆栈。反转内容三次最终会反转原始内容,这是必需的。

答案 3 :(得分:0)

看起来你应该写while not stack.is_empty():

(编辑后)好了,现在应该说stack = new_stack而不是return new_stack。应使用stack = reverse(stack)调用该函数。

(回应评论)如果返回值不是一个选项,那么我们需要知道修改Stack对象的方法。说stack = new_stackstack = Stack()不会在函数之外更改它。

这样的事情应该有效:

def reverse(stack):
    new_stack = Stack()
    while not stack.is_empty():
        new_stack.push(stack.pop())
    stack._items = new_stack._items

然而,这可能是一个坏主意,因为_items前面的下划线表明编写Stack类的人不希望以这种方式使用它。

正如@ user4815162342指出的那样,这可能会使堆栈反转两次,因此我们应该使用临时列表而不是使用临时new_stack = Stack()。真的@ user4815162342的答案是最好的答案。

答案 4 :(得分:0)

如果Stack类是您的,或者您可以扩展它,那么另一种反转堆栈的方法是保持所有数据的完整性,并跟踪堆栈的上升方向(成长或向下)并推送/根据堆栈方向弹出堆栈的顶部或底部。然后,您的堆栈反向方法就是更改标志的情况,该标志确定您的堆栈是增长还是减少。

我还没有任何代码,但是如果你的堆栈很大,那么改变一个标志可能比反转一大堆数据简单得多。

答案 5 :(得分:0)

class Stack():
    def __init__(self):
        self.item=[]
        self.n=0
    def __len__(self):
        return self.n
    def isEmpty(self):
        return self.n==0
    def push(self,item):
        self.item.append(item)
        self.n+=1
    def pop(self):
        ele=self.item.pop()
        self.n-=1
        return ele
    def getPeek(self):
        if self.n>0:
            return self.item[-1]
        return "Stack is empty"
    def getStackitem(self):
        return [self.item[i] for i in range(self.n)]


def reversing(data):
    x=Stack()
    for i in data:
        x.push(i)
    y=Stack()
    while not x.isEmpty():
        y.push(x.pop())
    return "".join(y.getStackitem())

print(reversing("123456789")) 

答案 6 :(得分:-1)

首先复制堆栈,清空原始堆栈,然后按照您的方法。

def reverse(stack):
    old_stack = stack[:]
    while not stack.is_empty():
        stack.pop()
    while not old_stack.is_empty():
        stack.push(old_stack.pop())