1、思路分析 拿到这道题,会有以下几种思路: 思路一:
入队时,将所有的元素压入到s1中出队时,将s1中的所有元素倒入到s2中,然后让s2中栈顶的元素出栈,然后将s2中所有的元素倒入到s1中问题所在:我们不难发现,在这种解法中,要进行来回倒栈,时间复杂度就会比较大,做起来也比较麻烦 思路二: 说明:是对第一种的优化我们不难发现,其实在进行倒栈的时候,没必要进行最后一个元素的倒入
入队时,先判断s1是否为空,如果不为空,说明所有的元素都在s1中,此时将入队的元素直接压入s1中;如果s1为空,将s2中所有的元素倒入到s1中,将入队的元素压入s1中出队时,如果s2不为空,将s2栈顶的元素弹出,如果s2为空,将s1中除最后一个元素压入s2中,将最后一个元素出栈说明:这种方法其实是将两个栈更进一步的同时利用。每次出队后,并不将元素“倒回”s1,如果赶上下次还是出队操作,效率会高一些。 思路三:
入队时,将所有的元素压入s1出队时,判断s2是否为空,如果为不为空,直接将栈顶的元素弹出,如果s2为空,将s1中的元素倒入s2中,将最后一个元素弹出2、代码实现
(说明:对第三种方法的实现) #include<iostream> #include<stack> using namespace std; template<class T> class Queue { public: Queue() {} void Push(const T& x) { s1.push(x); } void Pop() { if(s1.empty() && s2.empty()) cout<<"队列为空,无法进行删除!"<<endl; if(s2.empty()) { while(!s1.empty()) { s2.push(s1.top()); s1.pop(); } } s1.pop(); } bool Empty() { return ((s1.empty()) && (s2.empty())); } T& Front() { if(s1.empty() && s2.empty()) { cout<<"队列为空!"<<endl; } if(s2.empty()) { while(!s1.empty()) { s2.push(s1.top()); s1.pop(); } } return s2.top(); } private: stack<T>s1; stack<T>s2; };1、思路分析: 要得到栈的最小元素 思路一: 每次压入数的时候,将所有的数进行排序,将最小的数放在栈顶,就保证了在O(1)的时间复杂度内得到最小的元素。但是这种做法不能保证最后入栈的元素最先出栈,已经不符合栈的特点了。 思路二: 我们加入一个辅助栈,当辅助栈不为空的时候,将压入的值压入两个栈,否则将要压入的值和辅助栈的值进行比较,如果比辅助栈的值小的话,就将此值压入到辅助栈中,否则就将辅助栈栈顶的值再进行压入一次。就是说辅助栈栈顶的值一直都是最小值。
2、代码实现
#include<iostream> #include<stack> using namespace std; template<class T> class MinStack { public: MinStack(){} void Push(const T& x) { s1.push(x); if (min.empty() || x < min.top()) min.push(x); else min.push(min.top()); } void Pop() { if (!min.empty() && !s1.empty()) { s1.pop(); min.pop(); } } const T& Min()const { return min.top(); } private: stack<T> s1; stack<T> min; };思路二:从中间分别向两边压栈 将数组的中间位置看做两个栈的栈底,压栈时栈顶指针分别向两边移动,当任何一边到达数组的起始位置或是数组尾部,则开始扩容。
思路三:从两边向中间压栈 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。
方案二和方案一当两栈中元素不同时,比较浪费空间,方案三节省空间 - 2、代码实现
template<class T> class TwoStack { public: TwoStack() :_a(NULL) , _top1(0) , _top2(0) , _capacity(0) { _CheckCapacity(); } ~TwoStack() { if (_a) delete[] _a; } void Push1(const T& d) { _CheckCapacity(); _a[_top1++] = d; } void Push2(const T& d) { _CheckCapacity(); _a[_top2--] = d; } void Pop1() { if (_top1 > 0) --_top1; } void Pop2() { if (_top2 < _capacity-1) _top2++; } size_t Size1() { return _top1; } size_t Size2() { return _capacity -1- _top2; } bool Empty1() { return _top1 == 0; } bool Empty2() { return _top2 == _capacity - 1; } T& Top1() { if (_top1>0) { return _a[_top1-1]; } } T& Top2() { if (_top2 < _capacity - 1) return _a[_top2+1]; } private: void _CheckCapacity() { if (_a == NULL) { _capacity += 3; _a = new T[_capacity]; _top2 = _capacity - 1; return; } if (_top1 == _top2) { size_t OldCapacity = _capacity; _capacity = _capacity * 2; T* tmp = new T[_capacity]; for (size_t i = 0; i < _top1; i++) { tmp[i] = _a[i]; } for (size_t j = OldCapacity-1,i=_capacity-1; j>_top2;j--,i--) { tmp[i] = _a[j]; } delete[] _a; _a = tmp; _top2 += _capacity / 2; } } private: T* _a; size_t _top1; size_t _top2; size_t _capacity; };