C++——stack和queue的使用和OJ练习题

 

目录

stack

简介

使用

模拟实现

queue

简介

使用

模拟实现

deque

简介

dqueue的优势

相关OJ题目

逆波兰表达式求值

 栈的压入、弹出序列

 最小栈


stack

简介

1、stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行 元素的插入与提取操作。

2、 stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定 的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下 操作:

  • empty:判空操作
  • back:获取尾部元素操作
  • push_back:尾部插入元素操作
  • pop_back:尾部删除元素操作

4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器, 默认情况下使用deque。

使用

成员函数功能
empty判断栈是否为空
size获取栈中有效元素个数
top获取栈顶元素
push元素入栈
pop元素出栈
swap交换两个栈中的数据

模拟实现

namespace cl //防止命名冲突
{
	template<class T, class Container = std::deque<T>>
	class stack
	{
	public:
		//元素入栈
		void push(const T& x)
		{
			_con.push_back(x);
		}
		//元素出栈
		void pop()
		{
			_con.pop_back();
		}
		//获取栈顶元素
		T& top()
		{
			return _con.back();
		}
		const T& top() const
		{
			return _con.back();
		}
		//获取栈中有效元素个数
		size_t size() const
		{
			return _con.size();
		}
		//判断栈是否为空
		bool empty() const
		{
			return _con.empty();
		}
		//交换两个栈中的数据
		void swap(stack<T, Container>& st)
		{
			_con.swap(st._con);
		}
	private:
		Container _con;
	};
}

queue

简介

1.队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端 提取元素。

2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的 成员函数来访问其元素。元素从队尾入队列,从队头出队列。

3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操 作: empty:检测队列是否为空 size:返回队列中有效元素的个数 front:返回队头元素的引用 back:返回队尾元素的引用 push_back:在队列尾部入队列 pop_front:在队列头部出队列

4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标 准容器deque。

使用

成员函数功能
empty判断队列是否为空
size获取队列中有效元素个数
front获取队头元素
back获取队尾元素
push队尾入队列
pop队头出队列
swap交换两个队列中的数据

模拟实现

namespace cl //防止命名冲突
{
	template<class T, class Container = std::deque<T>>
	class queue
	{
	public:
		//队尾入队列
		void push(const T& x)
		{
			_con.push_back(x);
		}
		//队头出队列
		void pop()
		{
			_con.pop_front();
		}
		//获取队头元素
		T& front()
		{
			return _con.front();
		}
		const T& front() const
		{
			return _con.front();
		}
		//获取队尾元素
		T& back()
		{
			return _con.back();
		}
		const T& back() const
		{
			return _con.back();
		}
		//获取队列中有效元素个数
		size_t size() const
		{
			return _con.size();
		}
		//判断队列是否为空
		bool empty() const
		{
			return _con.empty();
		}
		//交换两个队列中的数据
		void swap(queue<T, Container>& q)
		{
			_con.swap(q._con);
		}
	private:
		Container _con;
	};
}

deque

简介

 我们通过看文档会发现这个名为双端队列的容器居然如此强大,不仅弥补了vector和list的缺点,更是都具有vector和list的优点。当然,我们也知道,它肯定不会是无敌的存在,那么我们就不会再学习vector和list了。

它作为我们实现stack和queue的缺省参数,肯定有它的存在意义。

它通过一个中控指针数组来完成了很多效率很低的操作!

dqueue的优势

在实现stack与vector相比

扩容代码不大,不需要拷贝数据浪费空间也不多。

​​​​​在实现stack与list相比

cpu高速cache命中。其次不会频繁申请小块空间。申请和释放空间次数少代价低。

在实现queue与list相比:

cpu高速cache命中。其次不会频繁申请小块空间。申请和释放空间次数少代价低。

总结:

deque适合头尾插入删除,但是中间插入删除,和随机访问效率都差强人意。所以要高频随机访问还得是vector,要任意位置插入删除,还得是list。

相关OJ题目

解析见代码中的注释!

逆波兰表达式求值

力扣icon-default.png?t=M85Bhttps://leetcode.cn/problems/evaluate-reverse-polish-notation/

 

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(const auto& str : tokens)
        //利用范围for进行遍历
        {
            if(str=="+"||str=="-"||str=="*"||str=="/")
            //如果是操作符就进行操作
            {
                long right=st.top();
                st.pop();
                long left=st.top();
                st.pop();
            switch(str[0])
            //这里不能填写str因为switch只能支持整型
            //因此直接取它的第一个字符
            {
                case '+':
                st.push(left+right);
                break;

                case '-':
                st.push(left-right);
                break;

                case '*':
                st.push(left * right);
                break;

                case '/':
                st.push(left/right);
                break;

                default :
                assert(false);
            }
            }
            else
            {
                st.push(stoi(str));
                //将tokens中的字符串转为int型存放入栈中
            }
        }
        return st.top();
        //最终栈中剩下的数就是我们所需要的
    }
};

 栈的压入、弹出序列

栈的压入、弹出序列_牛客题霸_牛客网【牛客题霸】收集各企业高频校招笔面试题目,配有官方题解,在线进行百度阿里腾讯网易等互联网名企笔试面试模拟考试练习,和牛人一起讨论经典试题,全面提升你的技术能力icon-default.png?t=M85Bhttps://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        stack<int> st;
        //定义一个栈用来实现
        size_t pushi=0,popi=0;
        //分别用来遍历pushV和popV
        while(pushi<pushV.size())
        {
            st.push(pushV[pushi]);
            //将第一个vector中的数据入栈
            pushi++;
            //更新pushi
            while(!st.empty()&&st.top()==popV[popi])
            {
                st.pop();
                popi++;
            }
        }
        return popi==popV.size();


        
    }
};

 最小栈

力扣icon-default.png?t=M85Bhttps://leetcode.cn/problems/min-stack/ 

class MinStack {
public:

    MinStack() 
    {}
    
    void push(int val) {
        St.push(val);
        if(minSt.empty()||val<=minSt.top())
        {
            minSt.push(val);
        }

    }
    
    void pop() {
        if(St.top()==minSt.top())
        {
            minSt.pop();
        }
        St.pop();

    }
    
    int top() {
        return St.top();

    }
    
    int getMin() {
        return minSt.top();

    }
private:
    stack<int> minSt;
    stack<int> St;
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

袁百万

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

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

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

打赏作者

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

抵扣说明:

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

余额充值