栈和队列之经典(上篇)
2017-12-11 17:11
134 查看
要完成下面关于栈和队列的题目,首先要明白
栈的特性:后进先出
队列的特性:先进先出
(1)实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值的操作)的时间复杂度为O(1) 。
本题的关键是要得到栈的最小元素min,我们的第一反应可能是每次压入一个新的元素时,将栈里所有元素排序,让最小元素位于栈顶,但是这样破坏了栈的规律,它不能保证最后入栈的元素可以最先出栈。
同样,建立一个辅助栈存放最小元素,并且在最小元素出栈时我们希望能够得到次小元素,是不是可以把每次的最小元素(之前的最小元素和新压入栈的元素两者的较小值)都保存放进辅助栈,这样可以保证在每次更新后辅助栈的栈顶元素即为当前栈的最小元素。
![](https://img-blog.csdn.net/20171211124131137?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemp4NjI0Ympo/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
过程图:
![](https://img-blog.csdn.net/20171211133024178?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemp4NjI0Ympo/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
(2)使用两个栈实现一个队列
队列特性:先进先出
我们通过一个具体例子来分析往该队列插入和删除元素的过程。建立两个栈s1和s2,如下图:
![](https://img-blog.csdn.net/20180217225027815?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemp4NjI0Ympo/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
代码实现:
![](https://img-blog.csdn.net/20180217215615413?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemp4NjI0Ympo/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
总的来说,入队列就是直接压到s1就行了;出队列先把s1中的元素全部出栈压入到s2中,弹出s2中的栈顶元素。
(3)使用两个队列实现一个栈
我们通过一系列栈的压入和弹出操作来分析用两个队列模拟一个栈的过程。
![](https://img-blog.csdn.net/20180217224455168?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemp4NjI0Ympo/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
代码实现:
结果:
栈的特性:后进先出
队列的特性:先进先出
(1)实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值的操作)的时间复杂度为O(1) 。
本题的关键是要得到栈的最小元素min,我们的第一反应可能是每次压入一个新的元素时,将栈里所有元素排序,让最小元素位于栈顶,但是这样破坏了栈的规律,它不能保证最后入栈的元素可以最先出栈。
同样,建立一个辅助栈存放最小元素,并且在最小元素出栈时我们希望能够得到次小元素,是不是可以把每次的最小元素(之前的最小元素和新压入栈的元素两者的较小值)都保存放进辅助栈,这样可以保证在每次更新后辅助栈的栈顶元素即为当前栈的最小元素。
template<class T> class Stackwithmin { public: void Push(const T x) { _num.push(x); if(_min.empty()||x<=_min.top()) { _min.push(x);//当入栈元素小于辅助栈栈顶元素,即将此元素压入辅助栈 } } void Pop() { if(_num.top()==_min.top()) { _min.pop(); } _num.pop(); } T Min() { if(!_min.empty()) { return _min.top(); } } private: stack<T> _num; stack<T> _min; }; int main() { Stackwithmin<int> s; s.Push(4); s.Push(2); s.Push(5); s.Push(3); cout<<s.Min()<<endl; return 0; }
过程图:
(2)使用两个栈实现一个队列
队列特性:先进先出
我们通过一个具体例子来分析往该队列插入和删除元素的过程。建立两个栈s1和s2,如下图:
代码实现:
class QueueByTwoStack { public: QueueByTwoStack() {} void Push(const int& x) { s1.push(x); } void Pop() { if(!s2.empty()) { cout<<s2.top()<<" "; s2.pop(); } else { while(!s1.empty()) { s2.push(s1.top()); s2.pop(); } } } const int& Front() { if(!s2.empty()) { return s2.top(); } else { while(!s1.empty()) { s2.push(s1.top()); s1.pop(); } return s2.top(); } } size_t Size() { return s1.size()+s2.size(); } bool Empty() { return s1.empty() && s2.empty(); } private: stack<int> s1; stack<int> s2; }; int main() { QueueByTwoStack q; q.Push(1); q.Push(2); q.Push(3); q.Push(4); cout<<q.Front()<<endl; cout<<q.Size()<<endl; q.Pop(); q.Pop(); q.Pop(); q.Pop(); cout<<endl; return 0; }
总的来说,入队列就是直接压到s1就行了;出队列先把s1中的元素全部出栈压入到s2中,弹出s2中的栈顶元素。
(3)使用两个队列实现一个栈
我们通过一系列栈的压入和弹出操作来分析用两个队列模拟一个栈的过程。
代码实现:
#include<queue> class StackByTwoQueue { public: StackByTwoQueue() {} void Push(const int& x) { if(!q1.empty()) { q1.push(x); } else { q2.push(x); } } void Pop() { if(q2.empty()) { while(q1.size()!=1) { q2.push(q1.front()); q1.pop(); } cout<<q1.front()<<" "; q1.pop(); } else { while(q2.size()!=1) { q1.push(q2.front()); q2.pop(); } cout<<q2.front()<<" "; q2.pop(); } } const int& Top()//取栈顶 { if(q2.empty()) { while(q1.size()!=1) { q2.push(q1.front()); q1.pop(); } return q1.front(); } else { while(q2.size()!=1) { q1.push(q2.front()); q2.pop(); } return q2.front(); } } size_t Size() { return q1.size() + q2.size(); } bool Empty() { return (q1.empty() && q2.empty()); } private: queue<int> q1; queue<int> q2; }; int main() { StackByTwoQueue s; s.Push(1); s.Push(2); s.Push(3); s.Push(4); cout<<s.Size()<<endl; s.Pop(); s.Pop(); s.Pop(); s.Pop(); cout<<endl; }
结果:
相关文章推荐
- 堆——神奇的优先队列(上) 【经典】
- 秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据
- Hrbust 2171 最佳工厂【贪心+优先队列】经典题型
- java 经典队列
- C和指针 第十七章 经典数据类型 堆栈 队列 二叉树
- L. Right Build 【经典的最短路问题,dijkstra+优先队列】
- 经典面试题一:用两个栈实现一个队列
- BCB中的线程安全的消息队列(很经典)
- 经典算法题每日演练——第十九题 双端队列
- 消息队列--经典
- 2017最新PHP经典面试题目汇总(上篇)
- 【多线程】(十二)多线程十大经典案例之一双线程读写队列数据
- 经典算法19--双端队列
- 2017最新PHP经典面试题目汇总(上篇)
- 消息队列Kafka高可靠性原理深度解读上篇
- 经典数据结构之队列的链表实现方法
- Poj—2431 Expedition 优先队列使用经典例题
- 经典的数据结构——循环队列
- 入门经典_Chap06_例题[一]:队列,栈,链表的数组实现
- 经典算法和数据结构(一) 优先级队列与堆排序