1

To reverse a stack:

  1. I made a empty temporary stack
  2. I used tempstack.push(stack.pop())
  3. and then renamed it to stack = tempstack

but it doesn't seem to work. Any idea why?

To call this, I want to use just reverse(stack), not stack = reverse(stack).

def reverse(stack):
    new_stack = Stack()
    while not stack.is_empty():
        new_stack.push(stack.pop())
    stack = new_stack
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 1
    `stack = new_stack` will only make a difference *inside the function*, whatever object you passed in will be unaffected. Consider `return new_stack` then do `stack = reverse(stack)` outside. – jonrsharpe Oct 06 '15 at 16:50
  • @jonrsharpe well, what are other ways of renaming or mutating new_stack into stack? –  Oct 06 '15 at 16:51
  • 1
    Have you considered reading the documentation for the data structure you're using? – jonrsharpe Oct 06 '15 at 16:51
  • @jonrsharpe from what i can tell its a list using FIFO. Anything im missing? I dont really want to return anything. I want to just reverse the order of the values in stack. But there is no way to do this than to store all the pop values in to a temp data structure then renaming the temp data structure into the original one in my opinion. –  Oct 06 '15 at 16:53
  • I think you're missing @jonrsharpe's point. You aren't returning the reversed stack. When you call reverse() you should set that equal to stack and inside reverse() return the modified stack – SirParselot Oct 06 '15 at 17:00
  • If you absolutely do not want to return a value, you should have a look at [this](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) question. – bkaf Oct 06 '15 at 17:01

7 Answers7

3

If you're using actual lists to implement stacks (that is, if Stack inherits from list or basically is a list), then simply reverse the list in-place:

def reverse_stack(stack):
    stack.reverse()

I renamed the function to reverse_stack just to avoid confusion; you could still call it reverse. Example:

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

However, it seems that your Stack class doesn't inherit from list but keeps the underlying list in a private attribute, so you can't directly use any of the MutableSequence API on a Stack. Hence,

Version2, using only is_empty, push and pop methods of Stack

and using only Stacks, not lists or deques etc. First, a couple of helper functions:

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))

Now we can implement 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)
BrianO
  • 1,496
  • 9
  • 12
  • im trying to reverse it without using the reverse from lists. –  Oct 06 '15 at 17:08
  • Then I don't understand what you can and cannot do (as per a homework assignment, perhaps). You can use methods of `Stack` but we don't know what those are. Can you use `append` or `extend` of the underlying list class? – BrianO Oct 06 '15 at 17:11
  • for append, its basically 'push' which is just self._items.append(item). –  Oct 06 '15 at 17:14
  • Two questions: (1) Can you copy a stack? with a single method or using the constructor?, and (2) Can you empty a stack with a single method? – BrianO Oct 06 '15 at 17:21
  • I'm basically confined to using 3 methods of the Stack Class. 1. is_empty (self explanatory) 2. push 3. pop –  Oct 06 '15 at 17:25
  • OK, that's what i needed to know. Then @Robert Jacobs's answer is *almost* correct (now). Not quite, because he uses the `list` API to copy the data structure, which may or may not work on your `Stack` objects. In fact, it probably *wont* work: from your earlier comment, it looks like the underlying list is stored in an attribute `self._items`, so `Stack` probably does *not* inherit from `list` and slicing a `Stack` is probably undefined. – BrianO Oct 06 '15 at 17:26
2

As others pointed out, the last assignment doesn't do anything. However, the idea behind the exercise here is probably to only use the standard stack primitives push, pop, and is_empty, without relying on the exact stack implementation to make use of list.reverse and such.

The key point to notice is that stack is a last-in-first-out structure, so reading its contents automatically produces them in the reverse order. This is why a solution that uses another stack for temporary storage doesn't work:

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())

Here the stack contents get reversed twice: once when reading them from the original stack, and once when reading them from the temporary stack, so you end up with stack contents in the original order. To actually reverse a stack, you need extract the items into a list and then traverse it in order (from beginning to end), pushing the items on the original stack as they come:

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

Edit: inspired by BrianO's answer, here is a version that doesn't use a list at all (but does instantiate two temporary stacks):

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

Here the idea is to make use of the fact that copying the stack does reverse the contents - it's just that copying it back reverses it again. So we just copy it three times, first from the original stack to a temporary stack, then from a temporary stack to another temporary stack, and finally from the other temporary stack to the original stack. Reversing the contents three times ends up with the original contents reversed, which was required.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • ahh this makes the most sense out of all the answers! I cant believe I coudlnt think of this earlier –  Oct 06 '15 at 17:28
  • @kingwaffle: So you can use auxiliary `list`s after all? The constraints of the problem really were not clear. – BrianO Oct 06 '15 at 17:53
  • @BrianO I think the OP's point was that he can't just call `stack._items.reverse()` (or `stack.reverse()` if the stack were implemented as a list itself). This answer doesn't presume anything about the implementation of `Stack`. Still, I like your answer better because it doesn't rely on an external data structure at all, it does its magic with pure recursion. – user4815162342 Oct 06 '15 at 18:12
  • @user4815162342 Thanks. Yes eventually I got it that the `Stack` implementation is supposed to be opaque. I assumed that similarly it would be "cheating" (as in, too easy) to copy the elements to a two-way structure like a list or deque. If the question is a class assignment, the OP will find out soon enough ;) PS -- no "recursion" involved. – BrianO Oct 06 '15 at 18:19
  • PPS re "recursion" -- took me a moment to see what you meant: the nested calls to the same function. Since that function doesn't call *itself* (from its own body), strictly speaking recursion isn't involved. But yes that's where any cleverness resides. – BrianO Oct 06 '15 at 18:38
  • @BrianO Actually, I was misreading your code because I was thinking of recursion due to having tried to solve the problem using recursive calls for temporary storage. I've now included a variant of your solution in my answer, of course adding an explanation in my own words. – user4815162342 Oct 06 '15 at 18:41
1

Add a return value

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

and when calling the function do this:

stack = reverse(stack)

You are assigning value to stack inside function but not from where you called it. Issues with scope.

Xoul
  • 359
  • 1
  • 3
  • 13
  • what if i dont want to call it like stack=reverse(stack). I want to call it as just reverse(stack) –  Oct 06 '15 at 17:06
0

It looks like you should have written while not stack.is_empty():

(After the edit) Ok, now instead of stack = new_stack, it should say return new_stack. The function should be called with stack = reverse(stack).

(Responding to comments) If returning a value is not an option, then we need to know what methods there are to modify Stack objects. Saying stack = new_stack or stack = Stack() will not change it outside of the function.

Something like this should work:

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

However it's probably a bad idea because the underscore in front of _items shows that whoever wrote the Stack class didn't want it to be used that way.

Plus as @user4815162342 pointed out, this presumably reverses the stack twice, so instead of using a temporary new_stack = Stack() we should just use a temporary list. Really @user4815162342's answer is the best one.

Jim K
  • 12,824
  • 2
  • 22
  • 51
  • oh yes. i have that. I just forgot to add it in. Editing op now. –  Oct 06 '15 at 16:54
  • Or possibly just `while stack:`, if the implementation is sensible. – jonrsharpe Oct 06 '15 at 16:55
  • That doesnt work. Regardless, I dont think thats the problem of the code atm. –  Oct 06 '15 at 16:56
  • What if im confined to use reverse(stack) instead of calling it with stack = reversed(stack) –  Oct 06 '15 at 16:59
  • @kingwaffle then you will need to explicitly mutate the argument (in which case returning `None` is appropriate), but without knowing the implementation we can't tell you how. – jonrsharpe Oct 06 '15 at 17:02
  • regarding what methods what Stack has 1. is_empty which is just a bool that returns true if len(self._items) is equal to 0. 2. the usual pop 3. and the usual push –  Oct 06 '15 at 17:21
  • yeah since the _items indicated that it was a private variable. i didnt want to use it. –  Oct 06 '15 at 17:28
0

If the Stack class is yours or you can extend it, then another way of reversing the stack would be to keep all the data intact, and keep track of which way up your stack is (growing up or down) and either push/pop to the top or the bottom of the stack depending on the stack direction. Your stack reverse method is then simply a case of changing the flag which determines whether your stack grows up or down.

I don't have any code as yet, but if your stack is large then changing a flag may well be far simpler than reversing a large list of data.

Tony Suffolk 66
  • 9,358
  • 3
  • 30
  • 33
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")) 
sujit
  • 1
  • 1
-1

Copy the stack first, empty the original stack, then follow your method.

def reverse(stack):
    old_stack = stack[:]
    while not stack.is_empty():
        stack.pop()
    while not old_stack.is_empty():
        stack.push(old_stack.pop())
Robert Jacobs
  • 3,266
  • 1
  • 20
  • 30
  • 1
    `old_stack = stack` **does not** create a copy – jonrsharpe Oct 06 '15 at 17:13
  • Happily, `old_stack = stack[:]` does. – BrianO Oct 06 '15 at 17:25
  • @BrianO ...depending on its implementation – jonrsharpe Oct 06 '15 at 17:35
  • Yyyeah -- it copies lists, alright, but maybe not `Stack`s. It emerges, in fact, that it probably doesn't copy those at all. The class probably doesn't inherit from `list`, but keeps the underlying list in a private attribute. I addressed this in my answer & comments leading up to the Version2 there. – BrianO Oct 06 '15 at 17:45