【C++】stack and queue

目录

1. stack

1.1. stack常用接口实现

 2. queue

2.1. 常用接口模拟实现

3. 容器适配器

3.1. 适配器

3.2. STL标准库中stack和queue的底层结构

4.stack&queueOJ题

4.1.最小栈

4.2.栈的弹出、压入序列

4.3. 逆波兰表达式求值


1. stack

STL---stack文档

关于stack是什么和怎么用这里不再介绍。

实现也只是贴代码(毕竟太简单)。

1.1. stack常用接口实现

这里stack的实现与数据结构阶段的stack实现不同,不会去详细实现底层的结构,而是直接套用其他的容器来实现。所以stack和queue不是容器,而是容器适配器(下面讲)。

 

namespace wt
{
	template <class T, class container = deque<T>> // 第二个模板参数是容器,缺省值为deque(双端队列)
	class stack 
	{
	public:
		stack()  // 因为套用其他容器,可以使用他们自己的构造函数,所以stack的构造函数不用自己实现
		{}

		void push(const T& val)
		{
			_con.push_back(val);
		}

		void pop()
		{
			_con.pop_back();
		}

		const T& top()const
		{
			return _con.back();
		}

		int size()const
		{
			return _con.size();
		}

		bool empty()const
		{
			return _con.size() == 0;
		}
	private:
		container _con;
	};
}

 
2. queue

STL---queue文档

2.1. 常用接口模拟实现

 

namespace wt
{
	template <class T, class container = deque<T>>
	class queue
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}

		void pop()
		{
			_con.pop_front(); // 注意先进先出
		}

		T front()const
		{
			return _con.front();
		}

		int size()const
		{
			return _con.size();
		}

		bool empty()const
		{
			return _con.size() == 0;
		}
	private:
		container _con;
	};
}

3. 容器适配器

3.1. 适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

3.2. STL标准库中stack和queue的底层结构

虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和队列只是对其他容器的接口进行了包装。

STL中stack和queue默认使用deque,比如:

deque文档

至于什么是deque可以自己去了解。。。

 

4.stack&queueOJ题

4.1.最小栈

方法:

  • 使用两个栈,一个用来放原始数据(s1),一个用来放最小值(s2)
  • 入栈时如果s1放入的数比s2栈顶的小或相等,则将该数也放入s2,否则不放
  • 出栈时如果s1栈顶的数等于s2的栈顶,则s1、s2一起出栈

 代码如下:

class MinStack {
public:
    MinStack() 
    {}
    
    void push(int val) {
        s1.push(val);
        if(s2.empty()||val<=s2.top()) // s2为空或者入栈数小于等于s2栈顶
        {
            s2.push(val);
        }
    }
    
    void pop() {
        if(s1.top()==s2.top()) // s1.top等于s2.top时
        s2.pop();
        s1.pop();
    }
    
    int top() {
        return s1.top();
    }
    
    int getMin() {
        return s2.top(); // 返回s2栈顶
    }

    private:
    stack<int> s1;
    stack<int> s2;
};

4.2.栈的弹出、压入序列

方法:

  • 使用一个栈来模拟 该序列的压入
  • 当压入的数与弹出序列的数相等时,从栈中弹出该数,直到没有相等的数为止;否则继续压入
  • 当该序列全部入栈后,如果栈为空则说明压入顺序对应该弹出顺序,否则不对应

代码如下:

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        stack<int> s;
        size_t j = 0;
        for(size_t i = 0; i < pushV.size(); ++i)
        {
            s.push(pushV[i]);
            while(!s.empty()&&s.top()==popV[j]) // 当栈顶与弹出队列相等时,出栈
            {
                s.pop();
                ++j;
            }
        }
        if(s.empty())
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

 

4.3. 逆波兰表达式求值

逆波兰表达式又叫做后缀表达式,逆波兰表达式把运算量写在前面,把算符写在后面。 

方法:

  • 用一个栈来存放数字,遍历vector,遇到数字就入栈
  • 如果遇到符号则连续将两个数字出栈进行运算,将运算结果继续入栈
  • 最后栈中就只会剩下最终运算的答案

代码如下:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> s;
        for(const auto& str:tokens)
        {
            if(str == "+" || str == "-" || str == "*" || str == "/")
            {
                int right = s.top();
                s.pop();
                int left = s.top();
                s.pop();
                switch(str[0])
                {
                    case '+':
                    {
                        s.push(left+right);
                        break;
                    }
                    case '-':
                    {
                        s.push(left-right);
                        break;
                    }
                    case '*':
                    {
                        s.push(left*right);
                        break;
                    }
                    case '/':
                    {
                        s.push(left/right);
                        break;
                    }
                    default:
                        assert(false);
                }
            }
            else
            {
                s.push(stoi(str)); // 将字符串转化成数组入栈
            }
        }
        return s.top();
    }
};

  • 34
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风继续吹TT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值