现在的位置: 首页 > 综合 > 正文

cc150:使用两个栈实现一个队列(两种方法比较)

2019年11月03日 ⁄ 综合 ⁄ 共 1357字 ⁄ 字号 评论关闭

   队列是先进先出的数据结构(FIFO),栈是先进后出的数据结构(FILO), 用两个栈来实现队列的最简单方式是:进入队列则往第一个栈压栈, 出队列则将第一个栈的数据依次压入第二个栈,然后出栈。每次有数据进入队列, 都先将第二个栈的数据压回第一个栈,然后再压入新增的那个数据;
每次有数据出队列,都将第一个栈的数据压入第二个栈,然后第二个栈出栈。 代码很简单:

template <typename T>
class MyQueue{
public:
    MyQueue(){

    }
    ~MyQueue(){

    }
    void push(T val){
        move(sout, sin);
        sin.push(val);
    }
    void pop(){
        move(sin, sout);
        sout.pop();
    }
    T front(){
        move(sin, sout);
        return sout.top();
    }
    T back(){
        move(sout, sin);
        return sin.top();
    }
    int size(){
        return sin.size()+sout.size();
    }
    bool empty(){
        return sin.empty()&&sout.empty();
    }
    void move(stack<T> &src, stack<T> &dst){
        while(!src.empty()){
            dst.push(src.top());
            src.pop();
        }
    }

private:
    stack<T> sin, sout;
};

   对于上面的实现,我们可以稍作改进来提高效率。上面的实现方法,
数据在两个栈之间移动得太频繁了,必然会导致效率下降。事实上有些移动是没有必要的。 有数据进入队列时,我们不去管第二个栈是否有数据,只管往第一个栈压栈即可。 当数据出队列时,如果第二个栈有数据,那就出栈。 因为此时第二个栈的栈顶元素即为队列的队首元素;如果第二个栈没有数据, 这才将第一个栈的数据出栈移动到第二个栈,然后第二个栈再出栈。这样一来, 逻辑上相当于将一个队列从中间切开,第一个栈从栈顶到栈底对应队列的队尾到切开处, 第二个栈从栈顶到栈底对应队列的队首到切开处。这样简单的修改, 可以减少许多不必要的数据移动,提高效率。

<span style="font-size:18px;">template <typename T>
class MyQueue1{
public:
    MyQueue1(){

    }
    ~MyQueue1(){

    }
    void push(T val){
        sin.push(val);
    }
    void pop(){
        move(sin, sout);
        sout.pop();
    }
    T front(){
        move(sin, sout);
        return sout.top();
    }
    T back(){
        move(sout, sin);
        return sin.top();
    }
    int size(){
        return sin.size()+sout.size();
    }
    bool empty(){
        return sin.empty()&&sout.empty();
    }
    void move(stack<T> &src, stack<T> &dst){
        if(dst.empty()){
            while(!src.empty()){
                dst.push(src.top());
                src.pop();
            }
        }
    }

private:
    stack<T> sin, sout;    
};</span>

抱歉!评论已关闭.