栈和队列之经典(上篇)

要完成下面关于栈和队列的题目,首先要明白
栈的特性:后进先出
队列的特性:先进先出

(1)实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值的操作)的时间复杂度为O(1) 。
本题的关键是要得到栈的最小元素min,我们的第一反应可能是每次压入一个新的元素时,将栈里所有元素排序,让最小元素位于栈顶,但是这样破坏了栈的规律,它不能保证最后入栈的元素可以最先出栈。
同样,建立一个辅助栈存放最小元素,并且在最小元素出栈时我们希望能够得到次小元素,是不是可以把每次的最小元素(之前的最小元素和新压入栈的元素两者的较小值)都保存放进辅助栈,这样可以保证在每次更新后辅助栈的栈顶元素即为当前栈的最小元素。

template<class T>
class Stackwithmin
{
public:
    void Push(const T x)
    {
        _num.push(x);
        if(_min.empty()||x<=_min.top())
        {
            _min.push(x);//当入栈元素小于辅助栈栈顶元素,即将此元素压入辅助栈
        }
    }
    void Pop()
    {
        if(_num.top()==_min.top())
        {
            _min.pop();
        }
        _num.pop();
    }
    T Min()
    {
        if(!_min.empty())
        {
            return _min.top();
        }
    }
private:
    stack<T> _num;
    stack<T> _min;
};
int main()
{
    Stackwithmin<int> s;
    s.Push(4);
    s.Push(2);
    s.Push(5);
    s.Push(3);
    cout<<s.Min()<<endl;
    return 0;
}

这里写图片描述
过程图:
这里写图片描述
(2)使用两个栈实现一个队列
队列特性:先进先出
我们通过一个具体例子来分析往该队列插入和删除元素的过程。建立两个栈s1和s2,如下图:
这里写图片描述
代码实现:

class QueueByTwoStack
{
public:
    QueueByTwoStack()
    {}
    void Push(const int& x)
    {
        s1.push(x);
    }
    void Pop()
    {
        if(!s2.empty())
        {
            cout<<s2.top()<<" ";
            s2.pop();
        }
        else
        {
            while(!s1.empty())
            {
                s2.push(s1.top());
                s2.pop();
            }
        }
    }
    const int& Front()
    {
        if(!s2.empty())
        {
            return s2.top();
        }
        else
        {
            while(!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
            return s2.top();
        }
    }
    size_t Size()
    {
        return s1.size()+s2.size();
    }
    bool Empty()
    {
        return s1.empty() && s2.empty();
    }
private:
    stack<int> s1;
    stack<int> s2;
};
int main()
{
    QueueByTwoStack q;
    q.Push(1);
    q.Push(2);
    q.Push(3);
    q.Push(4);
    cout<<q.Front()<<endl;
    cout<<q.Size()<<endl;
    q.Pop();
    q.Pop();
    q.Pop();
    q.Pop();
    cout<<endl;
    return 0;
}

这里写图片描述
总的来说,入队列就是直接压到s1就行了;出队列先把s1中的元素全部出栈压入到s2中,弹出s2中的栈顶元素。
(3)使用两个队列实现一个栈
我们通过一系列栈的压入和弹出操作来分析用两个队列模拟一个栈的过程。
这里写图片描述
代码实现:

#include<queue>
class StackByTwoQueue
{
public:
    StackByTwoQueue()
    {}
    void Push(const int& x)
    {
        if(!q1.empty())
        {
            q1.push(x);
        }
        else
        {
            q2.push(x);
        }
    }
    void Pop()
    {
        if(q2.empty())
        {
            while(q1.size()!=1)
            {
                q2.push(q1.front());
                q1.pop();
            }
            cout<<q1.front()<<" ";
            q1.pop();
        }
        else
        {
            while(q2.size()!=1)
            {
                q1.push(q2.front());
                q2.pop();
            }
            cout<<q2.front()<<" ";
            q2.pop();
        }
    }
    const int& Top()//取栈顶
    {
        if(q2.empty())
        {
            while(q1.size()!=1)
            {
                q2.push(q1.front());
                q1.pop();
            }
            return q1.front();
        }
        else
        {
            while(q2.size()!=1)
            {
                q1.push(q2.front());
                q2.pop();
            }
            return q2.front();
        }
    }
    size_t Size()
    {
        return q1.size() + q2.size();
    }
    bool Empty()
    {
        return (q1.empty() && q2.empty());
    }
private:
    queue<int> q1;
    queue<int> q2;
};
int main()
{
    StackByTwoQueue  s;
    s.Push(1);
    s.Push(2);
    s.Push(3);
    s.Push(4);
    cout<<s.Size()<<endl;
    s.Pop();
    s.Pop();
    s.Pop();
    s.Pop();
    cout<<endl;
}

结果:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值