与栈相关的问题
1.设计一个栈,在其基础功能的基础上,设计一个getMin方法,每次调用时返回当前栈内的最小值。
要求:时间复杂度为O(1),可使用现成的栈结构。
思路:设计该栈有两个栈,一个保存正常数据stackData,一个保存正常数据中的较小值stackMin。在新数据压入栈时,比较其与stackMin中栈顶元素,如果新数据小于等于stackMin栈顶,则将其插入stackMin,否则舍弃。同样,在stackData出栈时,检查出栈元素和stackMin的栈顶元素是否相等,相等则stackMin也同样出栈,这样就保证了stackMin的顶部始终存储的是stackData中的最小元素。
如图压入3,4,5,1,2,1
代码如下
#include<iostream> #include<assert.h> #include<stack> using namespace std; template <class T> class mystack { private: stack<T> stackData; stack<T> stackMin; public: void push(T newNum); bool pop(); T getMin(); }; template<class T> void mystack<T>::push(T newNum) { stackData.push(newNum); if(stackMin.size() != 0) { if(stackMin.top() >= newNum)//在stackMin不为空时,新元素小于stackMin栈顶,则压入stackMin stackMin.push(newNum); } else stackMin.push(newNum); return; } template<class T> bool mystack<T>::pop() { if(stackData.size() == 0) return false; if(stackData.top() == stackMin.top()) { stackData.pop(); stackMin.pop(); } else stackData.pop(); return true; } template<class T> T mystack<T>::getMin() { assert(stackMin.size() != 0); return stackMin.top(); } int main() { mystack<int> ms; for(int i=10; i>0; --i) ms.push(i); for(int i=0; i<10; ++i) { cout<<"mystack min = "<<ms.getMin()<<endl; ms.pop(); } return 0; }
2.编写一个类,使用两个栈实现队列的基本功能poll,peek,add
(poll出队并返回队头元素,peek仅返回队头元素)
思路如下,设计两个栈,stackpush和stackpop,当要入队时,则向stackpush中压栈,当要出队时,将元素从stackpush弹出并压入stackpop中,这样从stackpop中弹出的即为队头元素。用图来说明
如图我们就可以清楚地看出来,如果要add元素时,队列中的元素应在stackpush中,当要poll或peek元素时,元素应该在stackpop中,所以,用一个flag来表明现在元素所在位置,0为队列为空,1表示元素在stackpush中,-1表示元素在stackpop中,这样每当要入队或出队时先查看当前元素所在位置,这样就知道是否需要将元素倒过来。
#include<iostream> #include<assert.h> #include<stack> using namespace std; template<class T> class myqueue { private: stack<T> stackpush; stack<T> stackpop; short flag; public: myqueue():flag(0){} void add(T input); T poll(); T peek(); }; template<class T> void myqueue<T>::add(T input) { if(flag == -1)//元素在stackpop中,先把元素倒回stackpush { while(!stackpop.empty()) { stackpush.push(stackpop.top()); stackpop.pop(); } } stackpush.push(input); flag = 1; return; } template<class T> T myqueue<T>::poll() { if(stackpush.size()==0 &&stackpop.size()==0) exit(1); if(flag == 1)//元素在stackpush中,先把元素倒回stackpop { while(!stackpush.empty()) { stackpop.push(stackpush.top()); stackpush.pop(); } } T res = stackpop.top(); stackpop.pop(); flag = -1; return res; } template<class T> T myqueue<T>::peek() { if(stackpush.size()==0 &&stackpop.size()==0) exit(1); if(flag == 1) { while(!stackpush.empty()) { stackpop.push(stackpush.top()); stackpush.pop(); } } T res = stackpop.top(); flag = -1; return res; } int main() { myqueue<int> mq; for(int i=0; i<10; ++i) mq.add(i); for(int i=0; i<20; ++i) { if(i%2) cout<<"poll = "<<mq.poll()<<endl; else cout<<"peek = "<<mq.peek()<<endl; } for(int i=0; i<10; ++i) mq.add(i); for(int i=0; i<20; ++i) { if(i%2) cout<<"poll = "<<mq.poll()<<endl; else cout<<"peek = "<<mq.peek()<<endl; } return 0; }
3.如何仅用递归操作来逆序一个栈
首先我们需要得到栈底元素并将其删除,然后再进行逆序即可
#include<iostream> #include<stack> using namespace std; template<class T> int getAndRemoveLastElement(stack<T> *st) { T res = st->top(); st->pop(); if(st->size() == 0)//递归循环,栈为空时说明到达栈底,返回栈底元素 return res; else { T last = getAndRemoveLastElement(st); st->push(res); return last; } } template<class T> void reverse(stack<T> *st) { if(st->size() == 0) return; else { T i = getAndRemoveLastElement(st);//依次抽取栈底元素 reverse(st);//直到为空 st->push(i);//然后再进行压栈 } } int main() { stack<int> st; for(int i=0; i<10; ++i) st.push(i); reverse(&st); for(int i=0; i<10; ++i) { cout<<st.top()<<" "; st.pop(); } cout<<endl; return 0; }
不积小流无以成江河