剑指Offer学习总结-用两个队列实现栈
本系列为剑指Offer学习总结,主要是代码案例的分析和实现:
书籍链接:http://product.dangdang.com/24242724.html
原作者博客:http://zhedahht.blog.163.com/blog/static/254111742011101624433132/
原作者博客链接有完整的项目代码下载。
用两个队列实现栈
题目
题目:用两个队列实现一个栈。 栈的声明如下, 请实现它的两个数 appendTop 和 deleteTop,
分别完成在栈的顶部插入节点操作和栈的顶部删除节点操作。
队列的定义如下
template <typename T> class CStack
{
public:
CStack(void);
~CStack(void);
//在队列末尾添加一个结点
void appendTop(const T& node);
//删除头结点
T deleteTop();
private:
queue queue1;
queue queue2;
};
一个栈中包含了两个队列,我们可以先来简单模拟一下队列在这里该怎么用。
思路分析
我们通过一系列栈的压入和弹出操作来分析用两个队列模拟个栈的过程。
先插入一个元素 a, 不妨先把它插入到 queue1, 此时 queue1 中的元素有{ a },queue2 为空
再压入两个元素 b 和 c, 还是插入到 stack1 中, 此时 stack1 中的元素有{ a,b,c }
其中 a 位于队列头部,c位于队列尾部, 而 queue2 仍然是空的.
我们试着删除一个元素,按照栈的特点,先进的需要后出。
最后进的是c,我们需要先出,但是c现在位于队列部,只能后出,
所以我们可以利用squeue2,将queue1中的除了队尾元素入队queue2,
然后queue1中出队。
这里我们假定队列1负责出栈入栈,队列2作为中转栈。
出队结束后,将中转站的元素重新入队队列1。
完整的解法:
这部分代码请读者自行修改替换源代码工程,网上很多参考都是错误的解决,读者一定要自行实践区分正确信息和错误信息。
template<typename T> void CStack<T>::appendTop(const T& element)
{
queue1.push(element);
//queue1负责入栈 出栈
}
template<typename T> T CStack<T>::deleteTop()
{
if(queue1.size()==0)
throw new exception("stack is empty");
else
{
//queue1仅保留一个元素
while (queue1.size() > 1)
{
T temp = queue1.front();
queue1.pop();
//queue2当做中转栈
queue2.push(temp);
}
T head = queue1.front();
queue1.pop();
//queue2元素重新返回queue1
while (queue2.size() > 0)
{
T temp = queue2.front();
queue2.pop();
queue1.push(temp);
}
return head;
}
}
思路改进
分析上边的过程,我们可以发现,
其实每次插入元素的队列 都是有元素的队列,
所以我们不强制指定 哪一个是中转队列,
哪个有元素哪个就是源队列,另一个空的就是中转队列。
完整的解法:
下边的这种写法 思路是对的 但是实际效果 出来并不正确 具体的情况还有待研究探讨 用指针的方式实现是可以的
下面给出C#版本的演示代码
class CStack<T>
{
private Queue<T> queue1 = new Queue<T>();
private Queue<T> queue2 = new Queue<T>();
// 在队列末尾添加一个结点
public void appendTop(T node)
{
if (queue1.Count != 0)
{
queue1.Enqueue(node);
}
else
{
queue2.Enqueue(node);
}
}
// 删除队列的头结点
public T deleteTop()
{
Queue<T> data_queue;
Queue<T> temp_queue;
if (queue1.Count != 0)
{
data_queue = queue1;
temp_queue = queue2;
}
else
{
data_queue = queue2;
temp_queue = queue1;
}
if (data_queue.Count == 0)
throw new Exception("栈为空");
else
{
//queue1仅保留一个元素
while (data_queue.Count > 1)
{
T temp = data_queue.First();
data_queue.Dequeue();
//中转站
temp_queue.Enqueue(temp);
}
T head = data_queue.Dequeue();
return head;
}
}
}