栈结构
颠倒一个栈的元素顺序
问题:假设有一个栈{1,2,3,4,5,6},6是栈顶,1是栈底,现在要把这个栈中的元素颠倒一下。
思路:最简单的办法当然是把栈中的元素依次pop到一个数组中,然后把这个数组再push回栈里面即可,但这样需要O(n)的辅助空间。
下面介绍一种仅使用O(1)辅助空间的算法,我们知道,可以使用递归来模拟栈的操作。我们借助函数递归pop元素,这样在递归的函数栈上依次有
{6,5,4,3,2,1},1是栈顶,6是栈底,然后在递归返回的时候,如何把当前元素塞到原栈的底部呢?这里借助了另一个递归!
C++代码实现如下:
void Add2Bottom(stack &s, int val){ int top; if (s.empty()) { s.push(val); } else { top = s.top(); s.pop(); Add2Bottom(s, val); s.push(top); } }void Reverse(stack &s) { int top; if (!s.empty()) { top = s.top(); s.pop(); Reverse(s); Add2Bottom(s, top); } }int main(){ int n; int array[6] = { 1,2,3,4,5,6}; stack s; for (n=0; n<6; n++) s.push(array[n]); Reverse(s); while (!s.empty()) { cout<<
栈的min函数
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)。
思路:利用辅助栈,每次对stack push/pop一个元素时,同时也要更新辅助栈(存储最小元素的位置),例如:
步骤 数据栈 辅助栈 最小值
1.push 3 3 0 32.push 4 3,4 0,0 33.push 2 3,4,2 0,0,2 24.push 1 3,4,2,1 0,0,2,3 15.pop 3,4,2 0,0,2 26.pop 3,4 0,0 37.push 0 3,4,0 0,0,2 0
C++代码实现:
#include#include #include using namespace std;template class CStackWithMin{ public: CStackWithMin(void) {} virtual ~CStackWithMin(void) {} T& top(void); const T& top(void) const; void push(const T& value); void pop(void); const T& min(void) const; private: deque m_data; // the elements of stack deque m_minIndex; // the indices of minimum elements};// get the last element of mutable stacktemplate T& CStackWithMin ::top(){ return m_data.back();}// get the last element of non-mutable stacktemplate const T& CStackWithMin ::top() const{ return m_data.back();}// insert an elment at the end of stacktemplate void CStackWithMin ::push(const T& value){ // append the data into the end of m_data m_data.push_back(value); // set the index of minimum elment in m_data at the end of m_minIndex if(m_minIndex.size() == 0) { m_minIndex.push_back(0); } else { if(value < m_data[m_minIndex.back()]) m_minIndex.push_back(m_data.size() - 1); else m_minIndex.push_back(m_minIndex.back()); }}// erease the element at the end of stacktemplate void CStackWithMin ::pop(){ // pop m_data m_data.pop_back(); // pop m_minIndex m_minIndex.pop_back();}// get the minimum element of stacktemplate const T& CStackWithMin ::min() const{ assert(m_data.size() > 0); assert(m_minIndex.size() > 0); return m_data[m_minIndex.back()];}
int main()
{ class CStackWithMin<int> stk;stk.push(3);
cout<<"min="<<stk.min()<<endl;stk.push(4);
cout<<"min="<<stk.min()<<endl;stk.push(2);
cout<<"min="<<stk.min()<<endl;stk.push(1);
cout<<"min="<<stk.min()<<endl;stk.pop();
cout<<"min="<<stk.min()<<endl;stk.pop();
cout<<"min="<<stk.min()<<endl;stk.push(0);
cout<<"min="<<stk.min()<<endl;}
栈的push、pop序列
输入两个整数序列,其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序。为了简单起见,我们假设push序列的任意两个整数都是不相等的。
比如输入的push序列是1、2、3、4、5,那么4、5、3、2、1就有可能是一个pop系列。因为可以有如下的push和pop序列:push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,这样得到的pop序列就是4、5、3、2、1。但序列4、3、5、1、2就不可能是push序列1、2、3、4、5的pop序列。
C++实现:
int verify(int in[], int out[], int N){ int n; int m = 0; stack s; for (n=0; n
用栈实现队列
设2 个栈为A和B,A用作入队,B用作出队。
队满:A满且B不为空;队空:A和B都为空;入队:(1) 如果A未满,将新元素push 入栈A;(2) 如果A已满,将栈A中所有元素依次pop 出并push 到栈B,然后将元素入栈A;出队:(1) 如果B为空,则将栈A 中所有元素依次pop 出并push 到栈B,然后将元素出栈B;(2) 如果B不为空,将栈B 的栈顶元素pop 出;
C++代码实现:
bool queue_empty(stack &s1, stack &s2){ return s1.empty() && s2.empty();}void enqueue(stack &s1, stack &s2, int val){ s1.push(val);}void dequeue(stack &s1, stack &s2, int &val){ int top; if (s2.empty()) { while (!s1.empty()) { top = s1.top(); s1.pop(); s2.push(top); } } if (!s2.empty()) { val = s2.top(); s2.pop(); } else { cout<<"error: queue is empty"<