栈与队列都是比较高级的数据结构,虽然不难,但有时有些问题也比较灵活,在《编程之美》与《剑指offer》上就有一些这样的题目。用队列模拟栈、用站栈模拟队列,以及现实队列与栈的最大值与最小值求解,这些都是基础的,只要理解栈的后进先出与队列的先进先出特点即可解决。
1、栈模拟队列
用两个栈,元素从一个栈stackA进入,从另一个栈stackB出来。进队列时直接添加到stackA,出队列时若stackA非空,则直接出,否则将stackB中元素全部初战装到stackA,然后从stackA出栈。
#ifndef MyQueue_H #define MyQueue_H #include<stack> using namespace std; class MyQueue { private: stack<int>stackA,stackB; public: void EnQueue(int); int DeQueuep(); }; void MyQueue::EnQueue(int key) { stackA.push(key); } int MyQueue::DeQueuep() { if(stackB.empty()) { while(!stackA.empty()) { stackB.push(stackA.top()); stackA.pop(); } if(stackB.empty()) throw new exception("队列已空!"); } int ret=stackB.top(); stackB.pop(); return ret; } #endif MyQueue_H
2、队列模拟栈
用两个队列,进栈时进入其中一个空的队列,出栈时将其中一个队列中的元素进入另外一个空的队列,最后一个元素不进入直接出队列模拟出栈。
#ifndef MyStack_H #define MyStack_H #include<queue> using namespace std; class MyStack { private: queue<int>queueA,queueB; bool tag; public: MyStack() { tag=false; } void push(int); int pop(); }; void MyStack::push(int key) { if(!tag)queueA.push(key); else queueB.push(key); } int MyStack::pop() { if(!tag) { if(queueA.empty()) throw new exception("栈为空"); while(queueA.size()>1) { queueB.push(queueA.front()); queueA.pop(); } tag=true; int ret=queueA.front(); queueA.pop(); return ret; } else { if(queueB.empty()) throw new exception("栈为空"); while(queueB.size()>1) { queueA.push(queueB.front()); queueB.pop(); } tag=false; int ret=queueB.front(); queueB.pop(); return ret; } } #endif MyStack_H
3、栈的最小值与最大值操作
以最小值为例,直接开辟个辅助栈储存即可。上代码。
#ifndef StackWithMin_H #define StackWithMin_H #include<stack> using namespace std; class StackWithMin { private: stack<int>stackEle,stackMin; public: int min(); void push(int); void pop(); int top(); bool empty(); }; int StackWithMin::min() { if(stackMin.empty()) throw new exception("栈为空!"); return stackMin.top(); } void StackWithMin::push(int key) { stackEle.push(key); if(stackMin.empty()) stackMin.push(key); else { if(key>stackMin.top()) stackMin.push(stackMin.top()); else stackMin.push(key); } } int StackWithMin::top() { if(stackEle.empty()) throw new exception("栈为空!"); return stackEle.top(); } void StackWithMin::pop() { if(stackMin.empty()) throw new exception("栈为空!"); stackEle.pop(); stackMin.pop(); } bool StackWithMin::empty() { return stackMin.empty(); } #endif StackWithMin_H
4、队列的最小值与最大值操作
此处可以用优先级队列(堆+队列),此处栈模拟。与栈模拟队列类比,只不过这里的栈要用3中的栈,即包含最小(大)值的栈,其他比较简单,在此不多说了。
#ifndef QueueWithMin_H #define QueueWithMin_H #include"StackWithMin.h" const int INF=1<<30; class QueueWithMin { private: StackWithMin staMinA,staMinB; public: void EnQueue(int); int min(); int DeQueuep(); }; void QueueWithMin::EnQueue(int key) { staMinA.push(key); } int QueueWithMin::DeQueuep() { if(staMinB.empty()) { while(!staMinA.empty()) { staMinB.push(staMinA.top()); staMinA.pop(); } if(staMinB.empty()) throw new exception("队列已空!"); } int ret=staMinB.top(); staMinB.pop(); return ret; } int QueueWithMin::min() { int retAMIn=INF,retBMIn=INF; if(!staMinA.empty()) retAMIn=staMinA.min(); if(!staMinB.empty()) retBMIn=staMinB.min(); return retAMIn<retBMIn?retAMIn:retBMIn; } #endif QueueWithMin_H
由于每个元素出入两个队列或栈的次数为常数,所以总的时间复杂度与直接用栈或队列相同,且最值求解的时间复杂度为O(1),是典型的牺牲空间换取时间。
由于时间有限,欠缺测试,如有错误或不足,欢迎斧正!