用两个栈实现一个队列
1、线性表分为:顺序表和链表。
栈:只允许在尾上(即是栈顶)进行插入与删除。
队列:它是在队尾插入,队头删除。
2、栈选数组(即顺序表)结构时(比选链表结构更好):因为选数组结构可以进行size++与size--,而且效率高。
栈选链表结构:
3、队列选数组结构时:选数组结构不好,因为删除时需要整体前移,因为队列是在队头进行删除,删除了队头元素时,其后面所跟的其他元素就需要整体向前移一位。效率较低。
队列选链表结构时:比选数组结构好,因为插入和删除元素时方便。
#include <iostream>
#include <stack>
#include <assert.h>
using namespace std;
//2、两个栈实现一个队列
//思路:当两个栈都为空时,只能做入队操作,当两个栈不都为空时,入队、出队操作都可以实现。
// inSta主要用于入栈,outSta主要用于出栈
//过程:
// 入队:1、当outSta为空时,入队操作相当于对inSta做入栈操作(包括inSta为空和inSta不为空两种情况)
// 2、当inSta为空,outSta不为空(即上一操作为出栈,inSta转移到outSta的元素没有转移回inSta)时,此时先把outSta的所有元素出栈,
// 并按照出栈顺序入栈到inSta,然后再把此时要入队列的元素入栈到inSta
// PS:不会出现inSta不为空,outSta不为空的情况,这种情况只会在前一操作为入队列的出队列过程中(inSta的元素除栈底元素外全部转移
// 到outSta),然后这一操作执行前outSta为空,执行后,inSta为空
// 出队:1、当inSta、outSta都为空时,队列里面无元素,无法实现出栈
// 2、当inSta不为空,outSta为空时,把inSta除栈底元素外的所有元素出栈,并按照出栈顺序入栈到outSta,把inSta的栈底元素出栈
// 3、当inSta为空,outSta不为空时,说明上一操作为出栈,inSta转移到outSta的元素没有转移回inSta,此时把outSta的栈顶元素出栈即可
// PS:不会出现两个栈都不为空的情况,这种情况只会在前一操作为入队列的出队列时,然后这一操作执行前outSta为空,执行后,
// Stack1为空
template<typename T>
class TwoStackForQueue
{
public:
TwoStackForQueue()
{
//利用stack的构造函数完成
}
TwoStackForQueue(const TwoStackForQueue<T>& que)
{
//调用stack的赋值运算符重载/拷贝构造函数
inSta = que.inSta;
outSta = que.outSta;
}
~TwoStackForQueue()
{
//这儿不用做什么事情,两个栈开辟的空间由satck释放
}
void Push(const T& t)
{
if (outSta.size() == 0) //说明上一操作为入队操作或队列此时为空
{
inSta.push(t);
}
else
{
//先把outSta里面的元素按其出栈顺序入栈到inSta
while (outSta.size() != 0)
{
inSta.push(outSta.top());
outSta.pop();
}
inSta.push(t);
}
}
void Pop()
{
assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况
if (outSta.size() == 0)
{
//把inSta的栈底元素留下,直接出栈它的栈底元素即可
while (inSta.size() != 1)
{
outSta.push(inSta.top());
inSta.pop();
}
inSta.pop();
}
//说明上一操作为出栈,此时直接出栈outSta的栈顶元素即可
else
{
outSta.pop();
}
}
T& Front()
{
assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况
if (outSta.size() != 0)
{
return outSta.top();
}
else
{
//这儿不要图方便,留下inSta的栈底元素不移动,直接返回inSta的栈底元素,因为这样做的话使inSta和outSat都不为空了,
//而上面的Push与Pop没有对这种情况进行处理
while (inSta.size() != 0)
{
outSta.push(inSta.top());
inSta.pop();
}
return outSta.top();
}
}
T& Back()
{
assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况
if (outSta.size() != 0)
{
//这儿不要图方便,留下outSta的栈底元素不移动,直接返回outSta的栈底元素,因为这样做的话使inSta和outSat都不为空了,
//而上面的Push与Pop没有对这种情况进行处理
while (outSta.size() != 0)
{
inSta.push(outSta.top());
outSta.pop();
}
return inSta.top();
}
else
{
return outSta.top();
}
}
bool Empty()
{
if (inSta.size() == 0 && outSta.size() == 0)
{
return true;
}
else
{
return false;
}
}
size_t Size()
{
//要么两个栈都为空-->返回0,要么一个为空一个不为空-->返回两个栈中不为空的栈的size即可
return inSta.size() > outSta.size() ? inSta.size() : outSta.size();
}
//为了测试正确性,写一个输出运算符重载
template<typename T>
friend ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que);
private:
stack<T> inSta;
stack<T> outSta;
};
template<typename T>
ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que)
{
TwoStackForQueue<T> coutque(que);
os << "Queue: ";
//根据入队序列输出 inSta栈顶-->最后入队的元素 outSta-->最先入队的元素
//所以先把元素都先入栈到outSta,每次输出outSta的栈顶元素,并把它出栈,直到outSta里面没有元素即可
if (coutque.inSta.size() > 0)
{
while (coutque.inSta.size() > 0)
{
coutque.outSta.push(coutque.inSta.top());
coutque.inSta.pop();
}
}
while (coutque.outSta.size() > 0)
{
os << coutque.outSta.top() << " ";
coutque.outSta.pop();
}
os << "NULL";
return os;
}
void Test()
{
TwoStackForQueue<int> que;
que.Push(0);
que.Push(5);
que.Push(4);
que.Push(1);
que.Push(2);
que.Push(3);
cout << que << endl;
que.Pop();
que.Pop();
cout << que << endl;
cout << que.Front() << endl;
cout << que.Back() << endl;
cout << que.Empty() << endl;
cout << que.Size() << endl;
}
int main()
{
Test();
return 0;
}
//优化版一
//2、两个栈实现一个队列
//思路:当两个栈都为空时,只能做入队操作,当两个栈不都为空时,入队、出队操作都可以实现。
// inSta只用于入栈,outSta只用于出栈
//过程:
// 入队:不管outSta是否为空,都直接把元素入栈到inSta
// 出队:1、当inSta、outSta都为空时,队列里面无元素,无法实现出栈
// 2、当outSta为空时,把inSta除栈底元素外的所有元素出栈,并按照出栈顺序入栈到outSta,把inSta的栈底元素出栈
// 3、当outSta不为空时,说明上一操作为出栈,此时把outSta的栈顶元素出栈即可
template<typename T>
class TwoStackForQueue
{
public:
TwoStackForQueue()
{
//利用stack的构造函数构造inSta与outSta即可
}
TwoStackForQueue(const TwoStackForQueue& que)
{
inSta = que.inSta;
outSta = que.outSta;
}
~TwoStackForQueue()
{
//inSta和outSta空间的释放由stack类来完成
}
void Push(const T& t)
{
inSta.push(t);
}
void Pop()
{
assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况
if (outSta.size() == 0)
{
//说明此时是第一次执行出对列或之前outSta里面的数据全部被出栈了
while (inSta.size() != 1)
{
outSta.push(inSta.top());
inSta.pop();
}
inSta.pop();
}
//说明之前留在outSta里面的元素没有被全部出栈
else
{
outSta.pop();
}
}
T& Front()
{
assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况
if (outSta.size() != 0)
{
return outSta.top();
}
else
{
//当outSta为空时,说明队首元素即是inSta的栈底元素,返回它即可
while (inSta.size() != 1)
{
outSta.push(inSta.top());
inSta.pop();
}
return inSta.top();
}
}
T& Back()
{
assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况
if (inSta.size() != 0)
{
return inSta.top();
}
else
{
//当inSta为空时,说明队尾元素即是outSta的栈底元素,返回它即可
while (outSta.size() != 1)
{
inSta.push(outSta.top());
outSta.pop();
}
return outSta.top();
}
}
bool Empty()
{
if (inSta.size() == 0 && outSta.size() == 0)
{
return true;
}
else
{
return false;
}
}
size_t Size()
{
//返回两个栈的元素个数和
return inSta.size() + outSta.size();
}
//为了测试正确性,写一个输出运算符重载
template<typename T>
friend ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que);
private:
stack<T> inSta;
stack<T> outSta;
};
template<typename T>
ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que)
{
TwoStackForQueue<T> coutque(que);
os << "Queue: ";
//根据入队序列输出 inSta不为空:inSta栈顶-->最后入队的元素 outSta不为空:outSta栈顶-->最先入队的元素
while (coutque.outSta.size() > 0)
{
os << coutque.outSta.top() << " ";
coutque.outSta.pop();
}
while (coutque.inSta.size() > 0)
{
coutque.outSta.push(coutque.inSta.top());
coutque.inSta.pop();
}
while (coutque.outSta.size() > 0)
{
os << coutque.outSta.top() << " ";
coutque.outSta.pop();
}
os << "NULL";
return os;
}
void Test()
{
TwoStackForQueue<int> que;
que.Push(0);
que.Push(5);
que.Push(4);
que.Push(1);
que.Push(2);
que.Push(3);
cout << que << endl;
que.Pop();
que.Pop();
cout << que << endl;
cout << que.Front() << endl;
cout << que.Back() << endl;
cout << que.Empty() << endl;
cout << que.Size() << endl;
}
int main()
{
Test();
return 0;
}
本文出自 “10911544” 博客,请务必保留此出处http://10921544.blog.51cto.com/10911544/1773535