用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成再队列尾部插入结点和在队列头部删除结点 的功能
删除一个元素的步骤是:当stack2中不存在元素的时候,在stack2中的栈顶元素是最先进入队列的元素,可以弹出来,当stack2中为空的时候,> 我们把stack1中的元素逐个弹出并压入stack2.由于先进入队列的元素被压到stack1的底端,经过弹出和压入之后就处于stack2的顶端了,又可以直接 弹出。 插入一个元素,可以直接压入stack1中就行了,因为下次删除的时候才会影响到顶端元素。
#include<iostream>
#include<stack>
using namespace std;
template<class Type>
class CQueue
{
public:
CQueue();
~CQueue();
void appendTail(const Type& elements);
Type deleteHead();
private:
stack<Type> stack1;
stack<Type> stack2;
};
template<class Type>
CQueue<Type>::CQueue()
{
}
template<class Type>
CQueue<Type>::~CQueue()
{
}
template<class Type>
void CQueue<Type>::appendTail(const Type& elements)
{ //因为从尾部插入只需要放入到第一个栈当中即可
stack1.push(elements);
}
template<class Type>
Type CQueue<Type>::deleteHead()
{ //删除头结点需要借助第二个栈来 先把第一个栈当中的元素全部弹入到第二个栈当中,这样就实现队列的结构
if(stack2.size() <= 0)
{//stack2中没有元素 就可以向其中插入元素
while(stack1.size() > 0)
{
Type& data = stack1.top();
stack1.pop();
stack2.push(data);
}
}
if(stack2.size() == 0)
throw new exception();
Type head = stack2.top(); //保留头部并且返回
stack2.pop();
return head;
}
int main()
{
CQueue<int> qe;
qe.appendTail(1);
qe.appendTail(2);
qe.appendTail(3);
qe.deleteHead();
qe.deleteHead();
cout<<"Hello World"<<endl;
}
通过gdb调试可以看出来
Breakpoint 1, main () at search.cpp:326
326 CQueue<int> qe;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7_3.1.x86_64 libgcc-4.8.5-11.el7.x86_64 libstdc++-4.8.5-11.el7.x86_64
(gdb) n
327 qe.appendTail(1);
(gdb)
328 qe.appendTail(2);
(gdb)
329 qe.appendTail(3);
(gdb)
330 qe.deleteHead();
(gdb) p qe
$1 = {stack1 = std::stack wrapping: std::deque with 3 elements = {1, 2, 3}, stack2 = std::stack wrapping: std::deque with 0 elements}
(gdb) n
331 qe.deleteHead();
(gdb)
332 cout<<"Hello World"<<endl;
(gdb) p qe
$2 = {stack1 = std::stack wrapping: std::deque with 0 elements, stack2 = std::stack wrapping: std::deque with 1 elements = {3}}
和两个栈模拟一个队列的原理差不多,弹出一个元素的时候,根据栈先进后出的原则,最后入栈的元素应该最先被弹出。由于每次只能从队列的头部删除元素,因此我们可以先从队列1中删除元素并且插入到队列2中去.
#include<iostream>
#include<queue>
using namespace std;
template<class Type>
class CStack
{
public:
void appendTail(const Type& elements);
Type deleteHead();
private:
queue<Type> queue1;
queue<Type> queue2;
};
template<class Type>
void CStack<Type>::appendTail(const Type& elements)
{
queue1.push(elements);
}
template<class Type>
Type CStack<Type>::deleteHead()
{
Type tail;
if(queue2.size() <= 0)
{
while(queue1.front() != queue1.back())
{
Type& data = queue1.front();
queue1.pop();
queue2.push(data);
}
if(queue2.size() == 0)
throw new exception();
tail = queue1.front();
queue1.pop();
}
else
{
while(queue2.front() != queue2.back())
{
Type& data = queue2.front();
queue2.pop();
queue1.push(data);
}
if(queue1.size() == 0)
throw new exception();
tail = queue2.front();
queue2.pop();
}
return tail;
}
int main()
{
CStack<int> st;
st.appendTail(1);
st.appendTail(2);
st.appendTail(3);
st.deleteHead();
st.deleteHead();
cout<<"Hello World!"<<endl;
}
同样通过gdb调试
Breakpoint 1, main () at search.cpp:406
406 st.appendTail(1);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7_3.1.x86_64 libgcc-4.8.5-11.el7.x86_64 libstdc++-4.8.5-11.el7.x86_64
(gdb) n
407 st.appendTail(2);
(gdb)
408 st.appendTail(3);
(gdb)
409 st.deleteHead();
(gdb) p st
$1 = {queue1 = std::queue wrapping: std::deque with 3 elements = {1, 2, 3}, queue2 = std::queue wrapping: std::deque with 0 elements}
(gdb) n
410 st.deleteHead();
(gdb) p st
$2 = {queue1 = std::queue wrapping: std::deque with 0 elements, queue2 = std::queue wrapping: std::deque with 2 elements = {1, 2}}
(gdb) n
411 cout<<"Hello World!"<<endl;
(gdb) p st
$3 = {queue1 = std::queue wrapping: std::deque with 1 elements = {1}, queue2 = std::queue wrapping: std::deque with 0 elements}
(gdb)