栈和队列经典题目汇总
2017-07-22 15:33
246 查看
实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1)
1.用两个栈实现入栈:一个栈作为数据栈,一个栈作为最小值栈,往数据栈中直接压入数据,比较此时数据栈栈顶元素和min栈栈顶元素的大小,若min栈的栈顶元素小,则往min栈中压入栈顶元素,若要数据栈栈顶元素小,则压入数据栈栈顶元素。
出栈:数据栈和min栈同时pop
取最小值:取min栈的栈顶元素
//用两个栈实现 template<class T> class Stack1 { public: void Push(T d) { sData.push(d); if (sMin.empty() || sMin.top() > d) sMin.push(d); else sMin.push(sMin.top()); } void Pop() { if (!sData.empty()) { sData.pop(); sMin.pop(); } else return; } T& Min() { assert(!sMin.empty()); return sMin.top(); } private: stack<T> sData; //数据栈 stack<T> sMin; //最小值栈 };
2.用一个栈实现
入栈:min值的确定方法和两个栈时一样,不过数据和min值压入同一个栈,数据先压入,min值后压入。
出栈:pop两次。
取最小值:取栈顶元素值。
//用一个栈实现 template<class T> class Stack2 { public: void Push(T d) { if (s.empty() || s.top() > d) { s.push(d); s.push(d); } else { T tmp = s.top(); s.push(d); s.push(tmp); } } void Pop() { if (!s.empty()) { s.pop(); s.pop(); } else return; } T& Min() { assert(!s.empty()); return s.top(); } private: stack<T> s; };
push和pop都只进行了常数次,所以时间复杂度为O(1)
使用两个栈实现一个队列
1.保证在整个过程中,一个栈为空,则另外一个栈要么为空,要么有数据,不能出现两个栈同时有数据的情况,这样就可以借助为空的那个栈进行push和pop等操作了。template<class T> class Queue1 { public: void Push(T d) { if (s1.empty() && s2.empty()) { s1.push(d); } else if (!s1.empty() && s2.empty()) { s1.push(d); } else { s2.push(d); } } void Pop() { if (!s1.empty() && s2.empty()) { whil d993 e (!s1.empty()) //把所有的数放到s2中去 { s2.push(s1.top()); s1.pop(); } s2.pop(); //真正要删除的那个数 while (!s2.empty()) //把剩下的数放回s1中 { s1.push(s2.top()); s2.pop(); } } else if (s1.empty() && !s2.empty()) { while (!s2.empty()) //把所有的数放到s1中去 { s1.push(s2.top()); s2.pop(); } s1.pop(); //真正要删除的那个数 while (!s1.empty()) //把剩下的数放回s2中 { s2.push(s1.top()); s1.pop(); } } else return; } T& Front() { assert(!s1.empty() || !s2.empty()); if (!s1.empty() && s2.empty()) { while (!s1.empty()) //把所有的数放到s2中去 { s2.push(s1.top()); s1.pop(); } T top = s2.top(); //保存队头 while (!s2.empty()) //把所有的数放回s1中 { s1.push(s2.top()); s2.pop(); } return top; } else if (s1.empty() && !s2.empty()) { while (!s2.empty()) //把所有的数放到s1中去 { s1.push(s2.top()); s2.pop(); } T top = s1.top(); //保存队头 while (!s1.empty()) //把所有的数放回s2中 { s2.push(s1.top()); s1.pop(); } return top; } } T& Back() { assert(!s1.empty() || !s2.empty()); if (!s1.empty() && s2.empty()) { return s1.top(); } else if (s1.empty() && !s2.empty()) { return s2.top(); } } bool Empty() { return s1.empty() && s2.empty(); } size_t Size() { return s1.size() + s2.size(); } private: stack<T> s1; stack<T> s2; };
2.确保其中一个栈只能push,另一个栈只能pop
template<class T> class Queue2 { public: void Push(T d) { sIn.push(d); } void Pop() { if (sOut.empty()) { while (!sIn.empty()) { sOut.push(sIn.top()); sIn.pop(); } sOut.pop(); //队列真正要删除的数 } else { sOut.pop(); } } T& Front() { assert(!sIn.empty() || !sOut.empty()); if (sOut.empty()) { while (!sIn.empty()) { sOut.push(sIn.top()); sIn.pop(); } return sOut.top(); //保存队头 } else { return sOut.top(); //保存队头 } } T& Back() { assert(!sIn.empty() || !sOut.empty()); if (!sIn.empty()) { return sIn.top(); } else { while (!sOut.empty()) { sIn.push(sOut.top()); sOut.pop(); } return sIn.top(); } } bool Empty() { return s1.empty() && s2.empty(); } size_t Size() { return s1.size() + s2.size(); } private: stack<T> sIn; //sIn中只push stack<T> sOut; //sOut中只pop };
使用两个队列实现一个栈
template<class T> class Stack { public: void Push(T d) { if (!q1.empty() && !q2.empty()) { q1.push(d); } else if (!q1.empty() && q2.empty()) { q1.push(d); } else { q2.push(d); } } void Pop() { if (!q1.empty() && q2.empty()) { while (q1.size() != 1) { q2.push(q1.front()); q1.pop(); } q1.pop(); //栈真正要删除的数 } else if (q1.empty() && !q2.empty()) { while (q2.size() != 1) { q1.push(q2.front()); q2.pop(); } q2.pop(); //栈真正要删除的数 } else return; } T& Top() { assert(!q1.empty() || !q2.empty()); if (!q1.empty() && q2.empty()) { return q1.back(); } else if (q1.empty() && !q2.empty()) { return q2.back(); } } bool Empty() { return q1.empty() && q2.empty(); } size_t Size() { return q1.size() + q2.size(); } private: queue<T> q1; queue<T> q2; };
元素出栈、入栈顺序的合法性。如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)
bool IsPopOrder(const int *pPush, const int *pPop, int pushSize, int popSize) { assert(pushSize == popSize); stack<int> s; int i = 0; int j = 0; //1.把入栈序列中的元素压入栈,直至栈顶的数等于出栈序列的元素 for (i = 0; i < pushSize; i++) { s.push(pPush[i]); //2.栈顶的数等于出栈序列的元素时,弹出栈顶元素 while (!s.empty() && s.top() == pPop[j]) { s.pop(); ++j; } } //3.若栈为空,则序列合法 return s.empty() == 1 ? true : false; }
一个数组实现两个栈
1.栈1用数组的奇数位实现,栈2用数组的偶数位实现。2.把数组的中间位置当做栈底,栈1的栈顶朝左走,栈2的栈顶朝右走。
3.数组首元素位置作为栈1的栈底,数组尾元素位置作为栈2的栈底,栈1和栈2的栈顶都朝数组的中间走。
当栈1和栈2的数据个数相差较大时,第一种方法和第二种方法都会浪费数组空间,而第三种方法可以避免空间的浪费,故在此只实现第三种方法。
template<class T> class TwoStack { public: TwoStack() :_arr(NULL) , _top1(0) , _top2(0) , _capacity(0) { _CreateStack(); } ~TwoStack() { if (_arr) delete[] _arr; } void Push1(const T& d) { _CheckCapacity(); _arr[_top1] = d; //从0号位置放元素,_top1指向下一个未放元素的位置 _top1++; } void Push2(const T& d) { _CheckCapacity(); _arr[_top2] = d; //从_capacity-1号位置放元素,_top2指向下一个未放元素的位置 _top2--; } void Pop1() { if (_top1 > 0) { _top1--; } } void Pop2() { if (_top2 < _capacity - 1) { _top2++; } } T& Top1() { if (_top1 > 0) return _arr[_top1-1]; } T& Top2() { if (_top2 < _capacity - 1) return _arr[_top2+1]; } size_t Size1() { return _top1; } size_t Size2() { return _capacity - 1 - _top2; } bool Empty1() { return _top1 == 0; } bool Empty2() { return _top2 == _capacity-1; } void Print1() { for (int i = 0; i < _top1; i++) { cout << _arr[i] << " "; } cout << endl; } void Print2() { for (int i = _capacity - 1; i > _top2; i--) { cout << _arr[i] << " "; } cout << endl; } protected: void _CreateStack() { if (_arr == NULL) { _capacity = 3; _arr = new T[_capacity]; //对数组进行初始化 for (int i = 0; i < _capacity; i++) { _arr[i] = 0; } _top1 = 0; _top2 = _capacity - 1; } } void _CheckCapacity() { if (_top1 == _top2) { size_t oldCapacity = _capacity; _capacity *= 2; T* tmpArr = new T[_capacity]; //栈1的数据正着拷 for (size_t i = 0; i < _top1; i++) { tmpArr[i] = _arr[i]; } //栈2的数据倒着拷 size_t j = _capacity - 1; for (size_t i = oldCapacity - 1; i>_top2; i--) { tmpArr[j] = _arr[i]; j--; } delete[] _arr; _arr = tmpArr; _top2 += _capacity / 2; } } protected: T* _arr; //数组 size_t _top1; //栈1的栈顶 size_t _top2; //栈2的栈顶 size_t _capacity; //数组的容量 };
相关文章推荐
- 2017最新PHP经典面试题目汇总(上篇)
- PHP经典面试题目汇总(上篇)
- 单调队列经典题目 poj2823
- 最短路径问题经典题目汇总
- JavaScript经典题目汇总
- 2017最新PHP经典面试题目汇总(上篇)
- hdoj 1026 Ignatius and the Princess I 【BFS + 优先队列 + stack路径记录】 【经典题目】
- 2017最新PHP经典面试题目汇总(上篇)
- 面试准备系列02----面试中的栈和队列题目汇总
- 2017最新PHP初级经典面试题目汇总(下篇)
- 2017最新PHP经典面试题目汇总(上篇)
- 2017最新PHP初级经典面试题目汇总(下篇)
- 2015年9-10月互联网秋招经典面试题目汇总
- (初级)PHP经典面试题目汇总-沃森建站教程博客
- JAVA经典题目汇总
- 2017最新PHP初级经典面试题目汇总(下篇)
- 母函数 经典题目汇总
- 动态规划经典题目汇总
- 寒假第三周训练——栈队列题目汇总
- 数据结构经典算法汇总___循环队列: