C++ stack和queque

news2024/9/29 5:23:21

Stack

一.有关stack介绍

  1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其只能从容器的一端进行元素的插入、提取或者删除操作。
  2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定
    的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
  3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下
    操作:
    empty:判空操作
    back:获取尾部元素操作
    push_back:尾部插入元素操作
    pop_back:尾部删除元素操作
  4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,
    默认情况下使用deque。

二.适配器模式下stack的实现

1.设计模式

在这里插入图片描述

2.实现stack的代码

Stack.h头文件的实现:

#include<iostream>
#include<vector>
#include<list>
#include<deque>
using namespace std;
//栈后进先出的特性
namespace bit
{
	template<class T,class Container = vector<T>>
	//在使用vector做模板时,不能只引入#include<vector>,还要引入using namespace std;
	class Stack
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_back();
		}
		size_t size()
		{
			return _con.size();
		}
		bool empty()
		{
			return _con.empty();
		}
		T top()
		{
			return _con.back();
		}
	private:
		Container _con;
	};
}

测试类的实现

#include<iostream>
#include"Stack.h"

int main()
{
	bit::Stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);
	st.push(6);
	while (!st.empty())
	{
		cout << st.top() << endl;
		st.pop();
	}
	return 0;
}

三.有关stack的经典题

力扣题一:最小栈

https://leetcode.cn/problems/min-stack/
解法一:利用两个栈,第一个栈用来输入数列,第二个栈是对应第一个栈的每个元素对应的最小值
在这里插入图片描述
解法二:利用两个栈,第一个栈用来输入数列,第二个栈仍旧是输入最小值,但不是对应第一个栈的每个元素。只有最小值改变时才会压栈到第二个栈,并且如果最小值等于第一个栈的某元素,要重复压栈。
在这里插入图片描述
较第一种解法,空间消耗要低。
解法三:利用两个栈,第一个栈用来输入数列,第二个栈是存储一个结构体元素。该结构体分为两部分,一部分是最小值,第二部分是最小值的计数。
当第一个栈某个元素与当前最小值相等时,计数就加1。
在这里插入图片描述
该解法空间消耗率是比第二种要更低。
在这里,我们只显示第三种解法的代码。

#include<iostream>
using namespace std;
#include<stack>
class MinStack {
private:
    stack<int> st;
    struct Count
    {
        int min;
        int count;
    };
    stack<Count> minSt;
public:
    //因为在类和对象的知识,对于内置类型在构造函数中并不进行处理,对于其他数据类型会调用其本身的构造函数
    //所以在这里既可以删除构造函数,也可以保留不做任何处理
    MinStack() {

    }

    void push(int val) {
        st.push(val);
        if (minSt.empty())
        {
            Count cou;
            cou.min = val;
            cou.count = 1;
            minSt.push(cou);
            cout<<minSt.top().min<<minSt.top().count<<endl;
        }
        else
        {
            if (val < minSt.top().min)
            {
                Count cou1;
                cou1.min = val;
                cou1.count = 1;
                minSt.push(cou1);
            }
            else if (val == minSt.top().min)
            {
                minSt.top().count++;
            }
        }
    }

    void pop() {
        if (st.top() == minSt.top().min)
        {
            st.pop();
            minSt.top().count--;
            if(minSt.top().count==0)
            minSt.pop();
        }
        else
        {
            st.pop();
        }
    }

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

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

    };

力扣题二:栈的压入、弹出序列

https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking
解法:利用一个栈,来模拟实现出栈顺序。如果能和出栈的序列一一对应就说明是这样出栈是可行。先入栈序列中与出栈序列第一个不同的,入栈。当相同时,出栈跳到下一个元素,而该栈要pop该元素。再进行比较,如果入栈序列结束,直接就看栈和出栈序列接下来的元素是否可以一一对比。

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
    stack<int> _st;
    int i=0;
    for(auto e:pushV)
    {
        _st.push(e);

        while(!_st.empty()&&_st.top()==popV[i])
        {
            _st.pop();
            i++;
        }
    }
    return _st.empty();
    }
};

力扣题三:逆波兰表达式求值

https://leetcode.cn/problems/evaluate-reverse-polish-notation/
说明:逆波兰表达式就是后缀表达式,按操作符的优先顺序,先写左操作数,再写右操作数,最后写操作符。在我们日常生活中的数学表达式是中缀表达式。
比如:1+2*3/4-5
写为后缀表达式就为 1 2 3 * 4 / + 5 -
解法:利用一个栈来存储操作数,当遍历输入的字符串到操作符的时候,选择栈顶的两个元素进行计算。记住先出栈的是右操作符,后出栈的是左操作符。

#include<string>
using namespace std;
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
    stack<int> _st;
    for(auto str:tokens)
    {
        if(str=="+"||str=="-"||str=="*"||str=="/")
        {
            int right=_st.top();
            _st.pop();
            int left=_st.top();
            _st.pop();
            switch (str[0])
            {case '+':
                _st.push(left+right);
                break;
            case '-':
                 _st.push(left-right);
                break;
            case '*':
                 _st.push(left*right);
                break;
            case '/':
                 _st.push(left/right);
                break;
            }
        }
        else
        {
            //stoi函数功能是将n进制的字符串转换为十进制数字
            _st.push(stoi(str));
        }
    }
    return _st.top();
    }
};

Queue

一.有关queue的介绍

  1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
  2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
  3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操
    作:
    empty:检测队列是否为空
    size:返回队列中有效元素的个数
    front:返回队头元素的引用
    back:返回队尾元素的引用
    push_back:在队列尾部入队列
    pop_front:在队列头部出队列
  4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标
    准容器deque。

二.实现queue的代码

Queue.h的实现

#include<iostream>
#include<vector>
#include<list>
#include<deque>
using namespace std;
//队列先进先出的特性
namespace bit
{
	template<class T, class Container = list<T>>
	//在使用list做模板时,不能只引入#include<vector>,还要引入using namespace std;
	class Queue
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_front();
		}
		size_t size()
		{
			return _con.size();
		}
		bool empty()
		{
			return _con.empty();
		}
		T top()
		{
			return _con.front();
		}
	private:
		Container _con;
	};
}

测试类的实现

#include<iostream>
#include"Queue.h"

int main()
{
	bit::Queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);
	q.push(6);
	while (!q.empty())
	{
		cout << q.top() << endl;
		q.pop();
	}
	return 0;
}

三.有关queue的经典题目

用队列实现栈

https://leetcode.cn/problems/implement-stack-using-queues/
解法:用两个队列来解决。一个元素一个元素入栈,进栈的进行模拟。两个队列,一个队列是输入队列,一个是输出队列。当两个队列均为空,入栈的元素进入输入队列。当两个队列其一不为空,入栈的元素便进入不为空的队列。出栈的时候,将前size-1的元素挪到为空的队列,剩下的元素出队便为出栈。
在这里插入图片描述
代码如下:
class MyStack {
private:
queue q1;
queue q2;
public:
MyStack() {

}
//入栈
void push(int x) {
    if (q1.empty() && q2.empty())
        q1.push(x);
    else if (q1.empty() && !q2.empty())
        q2.push(x);
    else if (!q1.empty() && q2.empty())
        q1.push(x);
}

//出栈
int pop() {
    int ret = 0;
    if (q1.empty() && !q2.empty())
    {
        int i = q2.size() - 1;
        while (i--)
        {
            int tmp = q2.front();
            q2.pop();
            q1.push(tmp);
        }
        ret = q2.back();
        q2.pop();
    }
    else if (!q1.empty() && q2.empty())
    {
        int i = q1.size() - 1;
        while (i--)
        {
            int tmp = q1.front();
            q1.pop();
            q2.push(tmp);
        }
        ret = q1.back();
        q1.pop();
    }
    return ret;
}

int top() {
    int ret = 0;
    if (q1.empty() && !q2.empty())
        ret = q2.back();
    else if (!q1.empty() && q2.empty())
        ret = q1.back();
    return ret;
}

bool empty() {
    return q1.empty() && q2.empty();
}

};

deque、vector、list

一. 细讲deque

1.特性

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作(也就是可以进行头差头删、尾插尾删),且时间复杂度为O(1)。

2.底层实现示意图

在这里插入图片描述

3.使用

在这里插入图片描述

二.deque、vector、list的优缺点总结

deque的优点:1.可随机访问 2.支持头插头删
deque的缺点:1.随机访问较vector有一定消耗,不支持大量随机访问 2.中间插入删除要挪动数据,较list有一定的消耗
vector的优点:1.支持随机访问 2.CPU高速缓存命中高
vector的缺点:1.扩容消耗时间和空间 2.不支持头插头删以及中部的插入删除
list的优点:1.不需要扩容 2.支持头插头删以及中部的插入删除
list的缺点:1.不支持随机访问 2.CPU高速缓存命中低

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

u盘格式化后数据能恢复吗?当然可以,5步恢复U盘数据

很多人都知道格式化U盘会清空里面的数据&#xff0c;虽然可以进行备份&#xff0c;但是一般我们都不会轻易格式化自己的U盘。但是遇到一些特殊情况&#xff0c;我们必须格式化U盘。u盘格式化后数据能恢复吗&#xff1f;当然可以。 只要你的原始数据没有被覆盖&#xff0c;没有…

新C++(4):模板

"抱紧你的我,比国王富有" C可复用性高&#xff0c;C引入了模板的概念&#xff0c;后面在此基础上&#xff0c;实现了方便开发的标准模板库STL -----前言 一、初始模板 我们先来看看 下面的代码段; 如果此时又有需求&#xff1a; 交换一个char 类型的变量 &#x…

数据库,计算机网络、操作系统刷题笔记29

数据库&#xff0c;计算机网络、操作系统刷题笔记29 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle…

联合证券|主力加仓电气设备、有色金属等行业

上证指数、深证成指早盘探底上升&#xff0c;午后震动回落&#xff0c;尾盘有所上升&#xff1b;创业板指早盘探底冲高&#xff0c;午后震动回落&#xff1b;科创50指数早盘高开高走&#xff0c;午后震动回落。到收盘&#xff0c;上证指数报3157.64点&#xff0c;涨0.08%&#…

如何在Windows中轻松扩大C盘?

因为C盘是系统盘&#xff0c;所以没有足够的空间会导致电脑变慢&#xff0c;影响程序或游戏的运行。新电脑C盘可能有足够的可用空间&#xff0c;但随着对电脑的使用&#xff0c;应用程序安装的越来越多。即便很多程序安装到D盘&#xff0c;但某些程序仍然会占用C盘的部分空间。…

Linux信号通信之信号

文章目录什么是信号生活中的信号进程的信号Linux信号种类前台进程和后台进程进程对信号的处理策略Linux产生信号的方式系统调用发送信号kill调用raise调用abortalarm通过终端按键产生信号通过软件条件产生信号信号的自定义处理signalsigactionCoredump函数重入可重入函数和不可…

Spire.Office 8.1.1 for .NET 是 Spire.Office 7.12.5吗

为何 Spire.Office for .net 8.1.1 悄悄而来&#xff1f;不得而知。官网没有更新信息&#xff0c;为何&#xff1f;我们都不清楚&#xff0c;但是都需要迎接它的到来&#xff0c;不管何种原因&#xff0c;接受吧 by Ω578867473 Spire.Office 7.12.5 is released Friday, 30 De…

持续交付-Jenkinsfile 语法

实现 Pipeline 功能的脚本语言叫做 Jenkinsfile&#xff0c;由 Groovy 语言实现。Jenkinsfile 一般是放在项目根目录&#xff0c;随项目一起受源代码管理软件控制&#xff0c;无需像创建"自由风格"项目一样&#xff0c;每次可能需要拷贝很多设置到新项目&#xff0c;…

openEuler委员会主席江大勇:激发原创力量,逐梦数智未来

12月29日&#xff0c;由欧拉开源社区发起并联合华为、麒麟软件、统信软件、麒麟信安、超聚变、英特尔、中科院软件所、软通动力、润和软件等伙伴&#xff0c;共同举办的openEuler Summit 2022于线上举行。 会上&#xff0c;openEuler委员会主席江大勇发表了《激发原创力量&…

PyQt学习笔记-基本窗体

记述PyQt的基本窗体信息和基本操作。一、主窗体类&#xff08;QMainWindow&#xff09;主窗体类是通用的主窗体&#xff0c;包含菜单栏&#xff08;QMenuBar&#xff09;&#xff0c;工具栏&#xff08;QToolBars&#xff09;&#xff0c;悬停部件&#xff08;QDockWidgets&…

国产之光Yakit——POC模拟神器

概要介绍Yakit 是一个高度集成化的 Yak 语言安全能力的安全测试平台&#xff0c;使用 Yakit&#xff0c;可以做到&#xff1a;类 Burpsuite 的 MITM 劫持操作台查看所有劫持到的请求的历史记录以及分析请求的参数全球第一个可视化的 Web 模糊测试工具&#xff1a;Web FuzzerYak…

前端项目-小米商城

首页的展示 首页的功能 1、搜索栏模糊查询 在我在输入框输入关键字的时候&#xff0c;会匹配关键字&#xff0c;如果我的存放的数据里面包含这些关机键字就会显示出来。做到模糊查询的效果。 2、实现搜索功能 在首页的搜索框点击搜索的时候&#xff0c;就会对你输入的关键字进…

VCSA证书过期处理

原创作者&#xff1a;运维工程师 谢晋 前提提要 客户环境为VSAN环境&#xff0c;VCSA版本为6.7&#xff0c;登陆VCSA时发现报错如下图&#xff1a;     经验判断该报错是因为VCSA的证书过期了&#xff0c;登陆VCSA的5480界面https://VCSAIP:5480&#xff0c;发现果然是证…

Java设计模式-建造者模式Builder

介绍 建造者模式&#xff08;Builder Pattern&#xff09; 又叫生成器模式&#xff0c;是一种对象构建模式。它可以 将复杂对象的建造过程抽象出来&#xff08;抽象类别&#xff09;&#xff0c;使这个抽象过程的不同实现方 法可以构造出不同表现&#xff08;属性&#xff09;的…

模拟实现list和vector反向迭代器

学习这部分知识&#xff0c;需要你了解vector和list的正向迭代器知识以及容器适配器知识&#xff0c;可以阅读我写的另外三篇vector、list、容器适配器 知识的博客&#xff01;其中list知识内容尤其重要且难度要求很高&#xff01; 反向迭代器&#xff0c;顾名思义是与正向迭代…

Mybatis整合Spring的事务控制与SqlSession线程安全问题

在Spring与Mybatis框架整合中&#xff0c;主要有两个重要改动&#xff0c;分别是事务与SqlSession。mybatis-spring包中为以上两个问题提供了解决方案。 重要组件 SpringManagedTransaction &#xff08;Spring事务管理器&#xff09;SqlSessionTemplate &#xff08;SqlSess…

新年快到了,教大家用汇编语言显示Happy New Year!

新年快到了&#xff0c;教大家用汇编来显示Happy New Year! 文章目录新年快到了&#xff0c;教大家用汇编来显示Happy New Year!汇编老矣&#xff0c;尚能饭否&#xff1f;特点效率底层显示字符安装环境编写代码内存地址空间显示格式代码编译连接运行总结大家都知道&#xff0c…

使用Docker搭建主从数据库(MySQL)

很多人对主从数据库有一个误区&#xff0c;把多个MySQL搭建在同一个服务器上&#xff0c;性能提升是不是很有限&#xff1f;这个理念是错误的&#xff0c;数据库的性能瓶颈主要是在IO和CPU负载过高&#xff0c;在同一台服务器运行多个数据库&#xff0c;能带来更低的延迟&#…

Java中atomic包中的原子操作类总结

1. 原子操作类介绍 在并发编程中很容易出现并发安全的问题&#xff0c;有一个很简单的例子就是多线程更新变量 i1,比如多个线程执行 i操作&#xff0c;就有可能获取不到正确的值&#xff0c;而这个问题&#xff0c;最常用的方法是通过 Synchronized 进行控制来达到线程安全的目…

【自学Python】Python复数(complex)

Python复数(complex) Python复数(complex)教程 Python 可以支持复数&#xff0c;复数的虚部用 j 或 J 来表示。如果需要在程序中对复数进行计算&#xff0c;需要导入 Python 的 cmath 模块&#xff0c;在该模块下包含了各种支持复数运算的函数。 案例 复数 定义 Python 中…