《程序员代码面试指南》第一章 栈和队列(2)C++实现

本文介绍了如何使用两个栈实现队列,详细解析了具体实现过程和常见错误,包括数据的压入、弹出操作,以及在实现过程中遇到的问题和解决方案,强调了在数据传输和异常处理上的关键点。
摘要由CSDN通过智能技术生成

由两个栈组成的队列

【题目】

编写一个类,用两个栈实现队列,支持队列的基本操作(add、poll、peek)。

【解法】

使用两个栈,一个栈(stackOne)用来push,压入数据;压入完成后,再pop进另一个栈(stackTwo),这样就完成了数据的“反序”。

【具体实现】

1.声明

#include<iostream>
#include<stack>

using namespace std;

class MyQueue
{
public:
    MyQueue(){}
    ~MyQueue(){}
    void add(int elem);
    int poll();
    int peek();

private:
    stack<int> stackOne;
    stack<int> stackTwo;
};

2.实现

#include<iostream>
#include<stack>
#include<stdexcept>
#include"MyQueue.h"
using namespace std;

void MyQueue::add(int elem)
{
    stackOne.push(elem);
}

/*int MyQueue::poll()
{
    int value;
    //for(int i=0;i<stackOne.size();i++)//混淆了大小和长度
    for(int i=0;i<6;i++)
    {
    value=stackOne.top();
    stackOne.pop();
    stackTwo.push(value);
    }
    value=stackTwo.top();
    stackTwo.pop();
    return value;
}*/
/**********改进后的poll************/
int MyQueue::poll()
{
    int value;
    if(stackOne.empty() && stackTwo.empty())
        throw runtime_error("Empty Queue!");
    else if(stackTwo.empty())//stackTwo空时代表数据传输没有完成
    {
        while(!stackOne.empty())//stackOne不为空,继续传输
        {
        value=stackOne.top();
        stackOne.pop();
        stackTwo.push(value);
        }
    }
    value=stackTwo.top();
    stackTwo.pop();
    return value;
}

/*int MyQueue::peek()
{
    int top = poll();
    stackTwo.push(top);
    return top;
}*/
/**********改进后的peek************/
int MyQueue::peek()
{
    if(stackOne.empty() && stackTwo.empty())
        throw runtime_error("Empty Queue!");
    else if(stackTwo.empty())//stackTwo空时代表数据传输没有完成
    {
        while(!stackOne.empty())//stackOne不为空,继续传输
        {
        int value=stackOne.top();
        stackOne.pop();
        stackTwo.push(value);
        }
    }
    return stackTwo.top();
}

3.测试

#include <iostream>
#include "MyQueue.h"
using namespace std;

int main()
{
    int a[]={1,5,6,2,6,3};
    int i;
    MyQueue s;
    for(i=0;i<3;i++)
    {
        s.add(a[i]);

    }
     cout<<"s.peek: "<<s.peek()<<endl;
    for(;i<6;i++)
    {
        s.add(a[i]);
    }
    for(i=0;i<6;i++)
    {
    cout<<"s.peek: "<<s.peek()<<endl;
    s.poll();
    }

     return 0;
}

4.运行结果

 

【总结】

1.这道题最开始第一眼看起来感觉很简单,然后“快速”的就写出来了代码的初稿,最开始在测试代码中也没发现问题(有一方面是没有get测试的点,测试代码写的不好,没有体现出队列的特性)。

2.但在调试中发现运行时会出现异常退出。参考了标准代码后发现自己最开始写的代码对异常现象没有进行处理。并且在对两个栈之间进行数据传输时使用的是for循环,不便调试。这是第二阶段。

3.最后调试通过标准代码后,又来调试自己最开始写的代码,发现仍有异常退出。猜想是两个栈之间进行pop/push时出现了问题。才发现解题思路上出现了问题,当stackOne栈的数据传输到stackTwo栈之后,stackTwo中的顺序已经为队列的顺序,即之后的出列(poll)都应只对stackTwo中的数据进行操作;数据传输只需进行一次。而自己最开始写的代码中没有增加限制条件,导致调用一次就程序就要执行一次数据传输。因此标准代码中的判断栈空/非空的if条件和while条件地位重要。第一次看标准代码时没有深刻理解,综合来看这道题确实比第一题难一些。

 

【参考资料】

1.左神的《程序员面试代码指南》第一章中的第二个问题“由两个栈组成的队列”。

2.博客园Stan大神的个人博客 https://www.cnblogs.com/PrimeLife/p/5314204.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值