一、用两个栈实现队列
一般方法:stack1和stack2分别为两个栈,stack1作为存储栈,stack2作为临时缓冲区。入栈时元素直接放入stack1中,出栈时先将stack1中元素倒入stack2,出栈stack2第一个元素,然后把stack2中元素倒回stack1。将stack1中元素倒入stack2中时可以剩下最后一个直接作为结果弹出,这样就少一次入栈和出栈操作。
改进方法:入栈时元素添加到stack1中,出栈时元素从stack2出栈。出栈时可以不将元素倒回stack1,方便下次出栈。
出栈:stack2不空直接出栈;stack2空,stack1不空,把stack1中的倒入stack2;stack2空,stack1空,无元素可出栈;
入栈:直接入栈stack1即可,无论stack1和stack2空不空。这里有个问题就是stack1是否满了怎么办,这里如果stack2为空,那么可以将stack1中元素倒入stack2,再对stack1入栈,如果stack2不为空,那么就没有办法入栈了。
代码实现:
template<typename T> class SQueue{ public void SQueue(); void ~SQueue(); void appendTail(const T& node); T deleteHead(); private: Stack<T> stack1; Stack<T> stack2; }; template<typename T> void SQueue::appendTail(const T& element){ stack1.push(element); } template<typename T> T SQueue::deleteHead(){ if(stack2.size() <= 0){ while(stack1.size() > 0){ T& data = stack1.top(); stack1.pop(); stack2.push(data); } } if(stack2.size() == 0) throw new exception("queue is empty."); T head = stack2.top(); stack2.pop(); return head; }
二、用两个队列实现栈
已知两个队列queue1和queue2,拟实现栈的功能,一个存放着元素,另外一个作为暂时存放元素的队列。
实现出栈操作:如果元素在队列queue1中,那么只需将queue1中除最后入队的元素倒入queue2中,再将这最后入队的元素弹出即可;
实现入栈操作:看元素存放在哪个队列中直接入队即可。
实现取得栈的栈首元素:从存放元素的队列中进行back()操作。
可以设置两个标志位queue1_used和queue2_used用于标识哪个队列中存放着元素。
三、包含min函数的栈
定义栈的数据结构,在该类型中实现一个能够找到栈的最小元素的min函数,在该栈中,调用min、push、pop的时间复杂度都是O(1)。
思路:运用两个栈,一个数据栈,一个辅助栈,其中数据栈中存着数据,辅助栈中存着数据的最小值,这个时候就有一个问题,如果数据栈中的最小值出栈了,辅助栈中的值也要出栈,这样剩下的数据中的最小值是什么我们就无从得知了。因此,辅助栈中不能只存一个最小值,当最小元素弹出后,我们要可以得到次小元素,因此我们在压入这个最小元素前,我们要将最小元素保存起来。如果数据栈和辅助栈中的元素均为n,那么辅助栈的第n个元素表示数据栈中n个元素的最小值,辅助栈的第n-1个元素表示数据栈的前n-1个元素中的最小值,依此类推...
代码实现:
template<typename T> void StackWithMin<T>::push(const T& value){ sData.push(value); if(sMin.size() == 0 || value < sMin.top()) sMin.push(value); else sMin.push(sMin.top()); } template<typename T> void StackWithMin<T>::pop(){ assert(sData.size() > 0 && sMin.size() > 0); sData.pop(); sMin.pop(); } template<typename T> T& StackWithMin<T>::min() const{ assert(sData.size() > 0 && sMin.size() > 0); return sMin.top(); }
四、栈的压入、弹出序列
给出一个压入序列和一个弹出序列,判断对于压入序列,弹出序列是否是一个合法的序列。
思路:碰到弹出序列的一个元素,判断它是否和栈的top元素相同,如果相同的话,那么top元素出栈;如果不同,就将未入栈元素依次入栈直至遇到这个弹出序列的元素,如果未入栈元素全部入栈之后都未找到和弹出序列的这个元素相同的值,那么这个弹出序列就是非法的。
参考代码:
bool is PopOrder(const int * pPush, const int * pPop, int length){ bool flag = false; if(pPush != NULL && pPop != NULL && length > 0){ const int * pPushNext = pPush; const int * pPopNext = pPop; std::stack<int> s; while(pPopNext - pPop < length){ //因为这里要判断s的top值和弹出序列的值是否相同,所以要在外围判断pPopNext - pPop < length while(s.empty() || s.top() != *pPopNext){ if(pPushNext - pPush == length) break; s.push(*pPushNext); pPushNext++; } //进入这里有两种情况,首先s的top等于弹出序列的值,其次压入序列中没有元素了 if(s.top() != *pPushNext) break; s.pop(); pPopNext++; } if(s.empty()&& pPopNext - pPop == length) flag = true; } return flag; }
自己写的代码,如有错误,请指正:
bool isPopOrder(const int * pPush, const int * pPop, int length){ std::stack<int> s; bool flag = true; int i = j = 0; while(i < length && j < length){ if(s.size() != 0 && s.top() == pPop[j]){ s.pop(); j++; continue; } while(pPush[i] != pPop[j] && i < length){ s.push(pPush[i]); i++; } if(i >= lengh){ break; flag = false; } else{ j++; } } return flag; }