0

For some reason, I have to use a stack to achieve some function, but I need to reverse the output stack's elements. So I want to use stack<char,vector<char> to achieve direct access, but there may be some error in my suggestion. Can anyone tell me how to efficiently reverse the output stack's elements in C++ using STL stack?

dda
  • 6,030
  • 2
  • 25
  • 34
halostack
  • 993
  • 2
  • 13
  • 19
  • possible duplicate of [Trying to access an index of an std::stack](http://stackoverflow.com/questions/13428618/trying-to-access-an-index-of-an-stdstack) – Bo Persson Nov 17 '12 at 11:26

5 Answers5

3

Use a temporary stack.

// On exit the stack 's' will have it's elements reversed.
void reverse_stack(std::stack<int>& s)
{
    std::stack<int> tmp;
    while (!s.empty())
    {
        tmp.push(s.pop());
    }
    s.swap(tmp);
}
john
  • 85,011
  • 4
  • 57
  • 81
  • 1
    `s.swap(tmp)` should be more efficient. – juanchopanza Nov 17 '12 at 09:44
  • This will yield unfortunate results in terms of both time and space if the stack is large. – Richard Nov 17 '12 at 09:54
  • 1
    @john I don't like this because it destroys the original stack. I would never do this. Considering it as a legitimate operation is just insane. If I saw this in someones code I would consider them incompetent from then on. – evanmcdonnal Nov 17 '12 at 10:30
  • 3
    @evanmcdonnal I agree, but we don't know the context. The OP could have been explicitly asked to do this, he could be using the wrong algorithm and he doesn't really need to do this, maybe he's just been asked it as a puzzle type question. Generally I find it best to answer the question asked rather than just say 'you shouldn't do that'. – john Nov 17 '12 at 10:32
  • @john I do agree with that however, I think if you want to operate on a stack backwards you should traverse it using recursion so the stack remains intact for future operations. – evanmcdonnal Nov 17 '12 at 10:37
  • 1
    @evanmcdonnal Well there are other answers that address those issues. Hopefully the OP will find all the answers useful or interesting. – john Nov 17 '12 at 10:39
  • 1
    Thank you,I have use deque to instead of the stack. – halostack Nov 17 '12 at 11:05
  • 2
    wait a minute, `std::stack::pop()` returns `none`. You need: `tmp.push(s.top());` then `s.pop();` – HongboZhu Jan 30 '18 at 22:52
1

If you don't want to or you can't use stack in desired way, first you should think that do you really need stack? for example it might be better to use queue or deque in place of stack, so you can control it better!

BigBoss
  • 6,904
  • 2
  • 23
  • 38
1

If you want to access the elements in any order, why use a stack in the first place?

Use std::vector or std::deque directly, then iterate backwards like

for (auto iter = vec.rbegin(); iter != vec.rend(); ++iter) {
    process(*iter);
}

If you really need to, there's a hackish-but-correct way to access the stack's underlying container object.

See: how to print out all elements in a std::stack or std::queue conveniently

Community
  • 1
  • 1
Kos
  • 70,399
  • 25
  • 169
  • 233
0

In general you should not do this.

It's inappropriate to choose a container which is specifically designed to limit your access to its contents and then say that you really do want that access.

It's preferable to choose a container that's built to meet your needs. In this case using a deque seems more appropriate.

But, if you reeaaaaallllyyyy want to do something kind of stupid, this is how you'd access the members of the stack directly (note that this does not use gobs of extra memory and time to build a temporary reverse stack, as some of the other answers have suggested):

#include <stack>
#include <deque>
#include <cstdlib>
#include <iostream>
using namespace std;

template <class T, class S>
    S& Container(stack<T, S>& q) {
        struct HackedStack : private stack<T, S> {
            static S& Container(stack<T, S>& q) {
                return q.*&HackedStack::c;
            }
        };
    return HackedStack::Container(q);
}

int main()
{
    stack<int> st;
    deque<int> &mems = Container(st);

    cout<<"Putting numbers into the stack"<<endl;
    for(int i=0;i<20;i++){
        int temp=rand();
        cout<<temp<<endl;
        st.push(rand());
    }

    cout<<endl<<"Reading numbers in the stack"<<endl;
    for(deque<int>::iterator i=mems.begin();i!=mems.end();i++)
        cout<<*i<<endl;

    cout<<endl<<"Taking numbers out of the stack"<<endl;
    while(!st.empty()){
        int temp=st.top();
        st.pop();
        cout<<temp<<endl;
    }

    return 0;
}

And, yes, if you change all of the deque references to vector references, this will still work fine. But deque is probably the preferable container to use with your stack.

Richard
  • 56,349
  • 34
  • 180
  • 251
-1

To reverse the output use this simple recursive function (pseudo code)

  void recursiveWalk(Node* current)
  {
       if (current->next != NULL)
           recusiveWalk(current->next);
        // do stuff here
  }

  //call passing top
  recursiveWalk(stack->top);

This will build up the stack in reverse order. When you're on the last element the call stack will start to unwind allowing you to operate on the stack from bottom to top.

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • But beware ... [stack overflows](https://en.wikipedia.org/wiki/Stack_overflow)! This won't work if the stack is big. – Richard Nov 17 '12 at 09:53
  • @Richard This pushes 12 bytes onto the stack per call. We're not using Windows 95 and 256 MB of RAM. – evanmcdonnal Nov 17 '12 at 10:24
  • I think you misunderstand, @evanmcdonnal. Stack size is frequently significantly smaller than RAM unless explicitly adjusted. Large amounts of RAM will also be of little help if most of that RAM is being utilized by the program. – Richard Nov 17 '12 at 12:14
  • @Richard By default VC compiles with a stack size of 1 MB/thread. That means the default stack can afford to call this function more than 85,000 times. I don't think stack overflows are a serious concern in this kids homework assignment. They aren't even a serious concern in most enterprise software use cases. Unless I'm trying to recurse over my entire data set, or I work at FB or somewhere where a fraction of my data set could produce 85,000 nodes this isn't an issue. – evanmcdonnal Nov 17 '12 at 19:22
  • My comment was merely the necessary caution which should accompany a potentially unsafe algorithm - thank you for your pragmatic counterpoint. I don't doubt that there are many scenarios in which a recursive solution can be applied safely, but it is hubris to believe we always know our use-cases well enough to tell the difference. – Richard Nov 17 '12 at 20:01