数据结构(五)—— 栈与队列

news2024/12/25 0:32:51

文章目录

  • 前言
  • 一、基础
    • 1.1 stack
    • 1.2 queue
  • 二、题
    • 2.1 232 用栈实现队列
    • 2.2 225 用队列实现栈
    • 2.3 20 有效的括号
    • 2.4 1047 删除字符串中的所有相邻重复项


前言

灵魂四问:

1、C++中stack,queue 是容器么?
答:不是,而是容器适配器。

2、我们使用的stack,queue是STL(C++标准库)里面的两个数据结构,是哪个版本?
答:SGI STL。

3、我们使用的STL中stack,queue是如何实现的?
答:默认是以deque为缺省情况下的底层结构。

4、stack,queue 提供迭代器来遍历空间么?
答:不提供。

相信不仅仅是C++中有这些问题,那么大家使用其他编程语言,也可以考虑一下这四个问题,栈和队列是如何实现的。

栈与队列是我们熟悉的不能再熟悉的数据结构,但它们的底层实现,很多同学都比较模糊,这其实就是基础所在。

可以出一道面试题:栈里面的元素在内存中是连续分布的么?

这个问题有两个陷阱:

陷阱1:栈是容器适配器,底层容器使用不同的容器,导致栈内数据在内存中是不是连续分布。
陷阱2:缺省情况下,默认底层容器是deque,那么deque的在内存中的数据分布是什么样的呢? 答案是:不连续的,下文也会提到deque。

一、基础

在这里插入图片描述
栈和队列是STL(C++标准库)里面的两个数据结构。

1.1 stack

stack<int> sta;
sta.pop();
sta.push(x);
x = sta.top();

先进后出(弹夹)
栈提供 push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。 不像是 哈希set 或者 哈希map 提供迭代器iterator来遍历所有元素。

STL中stack往往不被归类为容器,而被归类为container adapter(容器适配器)。

栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。
那 STL 中栈是用什么容器实现的?从下图中可以看出,栈的内部结构,栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。
在这里插入图片描述
我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构。
deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了。

我们也可以指定vector为栈的底层实现,初始化语句如下:
std::stack<int, std::vector<int> > third; // 使用vector为底层容器的栈

1.2 queue

queue<int> que;
que.pop();
que.push(x);
x = que.front();

先进先出
STL queue也不被归类为容器,而被归类为container adapter( 容器适配器)。

队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器,SGI STL中队列一样是以deque为缺省情况下的底部结构。

也可以指定list 为起底层实现,初始化queue的语句如下:
std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列

二、题

2.1 232 用栈实现队列

在这里插入图片描述
思路:
1、使用两个栈,一个stIn、一个stOut
2、只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
3、peek()的实现,直接复用了pop(),功能相近的函数要抽象出来,不要大量的复制粘贴

class MyQueue {
public:
    stack<int> stIn;
    stack<int> stOut;
    /** Initialize your data structure here. */
    MyQueue() {

    }
    /** Push element x to the back of queue. */
    void push(int x) {
        stIn.push(x);
    }

    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        // 只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
        if (stOut.empty()) {
            // 从stIn导入数据直到stIn为空
            while(!stIn.empty()) {
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int result = stOut.top();
        stOut.pop();
        return result;
    }

    /** Get the front element. */
    int peek() {
        int res = this->pop(); // 直接使用已有的pop函数
        stOut.push(res); // 因为pop函数弹出了元素res,所以再添加回去
        return res;
    }

    /** Returns whether the queue is empty. */
    bool empty() {
        return stIn.empty() && stOut.empty();
    }
};

2.2 225 用队列实现栈

重点思路:
使用一个que即可,每次需要pop时,把que中的尾巴移动到front即可。
在这里插入图片描述

class MyStack {
public:
    queue<int> que;
    MyStack() {

    }
    
    void push(int x) {
        que.push(x);
    }
    
    int pop() {
        for(int i = 0; i < que.size()-1; ++i){
            int temp = que.front();
            que.pop();
            que.push(temp);
        }
        int temp = que.front();
        que.pop();
        return temp;
    }
    
    int top() {
        int temp = this->pop();
        que.push(temp);
        return temp;
    }
    
    bool empty() {
        return que.empty();
    }
};

2.3 20 有效的括号

括号匹配是使用栈解决的经典问题。
注意,本题“{ ( [ ) ] }”这种用例,出现为false(虽然他的左括号能够找到相应的右括号)

bool isValid(string s) {
        if (s.size() % 2 != 0) return false; // 如果s的长度为奇数,一定不符合要求
        stack<char> st;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '(') 
                st.push(')');
            else if (s[i] == '{') 
                st.push('}');
            else if (s[i] == '[') 
                st.push(']');
            // st中,只输入左括号对应的右括号
            
            // 如果到下面elseif说明此时s[i]为右括号
			// 此时st为空,直接false;或s[i]对不上前面的左括号,返回空
            else if (st.empty() || st.top() != s[i]) 
                return false;
            // st.top() 与 s[i]相等,栈弹出元素
            else if(st.top() == s[i])
                st.pop(); 
        }
        // 遍历完s了,检查st是否为空
        return st.empty();
}

2.4 1047 删除字符串中的所有相邻重复项

在这里插入图片描述

string removeDuplicates(string S) {
        string res;
        for(char s : S){
            if(res.empty() || res.back() != s) {
                res.push_back(s);
            }else{
                res.pop_back();
            }
        }
        return res;
    }

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

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

相关文章

高数基础3

目录 极限的概念&#xff0c;性质以及存在准则 求极限的方法 ​编辑 常用的基本极限 1的无穷次方常用的结论 例题&#xff1a; 方法2&#xff1a;利用等价无穷小代换求极限 例题&#xff1a; 常用的等价无穷小 利用有理运算法则求极限 例题 极限的概念&#xff0c;性质以…

【C语言】函数讲解(上)

【C语言】函数讲解&#xff08;上&#xff09; 1.函数是什么2.C语言中函数的分类2.1库函数2.1.1如何学会使用库函数 2.2.自定义函数 3.函数的参数3.1实际参数&#xff08;实参&#xff09;3.2形式参数&#xff08;形参&#xff09; 4.函数调用4.1传值调用4.2传址调用4.3练习 所…

Redis分布式锁实现方案

一、什么是分布式锁&#xff0c;与本地锁有什么区别 本地锁&#xff1a; 解决同一进程内多个线程操作同一资源的问题。 分布式锁&#xff1a; 解决多个进程同时操作同一资源的问题。 二、Redis的SETNX Redis之所以能实现分布式锁&#xff0c;得益于Redis的单线程处理模式&am…

Macbook(苹果电脑) VSCode 创建简单c++程序 配置C++开发环境

1.打开 Terminal 终端&#xff08;Command空格&#xff0c;输入Terminal&#xff09;。 1.1 输入如下指令&#xff0c;查看是否显示版本信息。 clang --version 1.2 如果出现版本信息&#xff0c;则跳过&#xff0c;否则输入 xcode-select --install 2. 为 VS Code 安装插件 …

docker中的四种网络模式

docker中的四种网络模式 实现原理四类网络模式host模式container模式none模式bridge模式 实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Con…

MySQL_第06章_多表查询

第06章_多表查询 讲师&#xff1a;尚硅谷 - 宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a; http://www.atguigu.com 多表查询&#xff0c;也称为关联查询&#xff0c;指两个或更多个表一起完成查询操作。 前提条件&#xff1a;这些一起查询的…

【Python】darts包(Python时序预测库的安装方法)+conda环境和库的建立

一、介绍 "darts"是一个Python编程语言中的数据处理和时间序列分析工具包。它提供了一系列用于处理、建模和分析时间序列数据的功能&#xff0c;包括时间序列的预处理、特征工程、模型训练和预测等。darts包含了许多常用的时间序列模型&#xff0c;如ARIMA、Prophet…

Linux权限 - 概念与管理 | 文件权限的修改与转让 【详解】

目录 Linux权限 Linux权限的概念 Linux权限的基础操作 (1).实现用户账号的切换 (2).仅提升当前指令的权限 Linux权限管理 1、文件访问者的分类&#xff08;人&#xff09; 2、文件类型和访问权限&#xff08;事物属性&#xff09; 3、文件权限值的表示方法 4、文件访…

数据结构与算法基础(王卓)(28):排序概述(分类)、直接插入排序思路

目录 排序分类&#xff1a;&#xff08;本章目录&#xff09; 按数据存储介质&#xff1a;&#xff08;学习内容&#xff09; 内部排序&#xff1a; 外部排序&#xff1a; 按比较器个数&#xff1a;&#xff08;学习内容&#xff09; 串行排序&#xff1a; 并行排序&…

arduino学习笔记2

一.蜂鸣器输出实验 1.源代码 int buzzer2;//设置控制蜂鸣器的数字口对应板子上2口 void setup() { pinMode(buzzer,OUTPUT);//设置对应的输出模式 } void loop() { unsigned char i,j;//定义变量while(1) { for(i0;i<50;i)//输出一个频率的声音{ digitalWrite(buzzer,H…

2023年4月的12篇AI论文推荐

GPT-4发布仅仅三周后&#xff0c;就已经随处可见了。本月的论文推荐除了GPT-4以外还包括、语言模型的应用、扩散模型、计算机视觉、视频生成、推荐系统和神经辐射场。 1、GPT-4 Technical Report Sbastien Bubeck, Varun Chandrasekaran, Ronen Eldan, Johannes Gehrke, Eric…

密码技术知识总结

密码技术知识总结 1. 密码技术简介 对称密码&#xff1a;加密和解密时使用同一密钥的方式公钥密码&#xff1a;加密和解密时使用不同密钥&#xff0c;也称非对称密码单向散列函数&#xff1a;保证数据的完整性&#xff0c;检测数据是否被篡改过 散列值&#xff1a;又称哈希值…

k8s 控制器---Statefulset

1. Statefulset 控制器 StatefulSet 是为了管理有状态服务的问题而设计的。 1.1 什么叫有状态服务&#xff1f; StatefulSet 是有状态的集合&#xff0c;管理有状态的服务&#xff0c;它所管理的 Pod 的名称不能随意变化。数据 持久化的目录也是不一样&#xff0c;每一个 Pod …

Unity --- UGUI --- Rect Transform(矩形变换) --- 锚点及其相关应用

1.所有的UI物体都没有Transform组件&#xff0c;取而代之的是Transform组件的派生 --- Rect Transform(矩形变换) 2.Rect Transform和Transform一样都有旋转和缩放&#xff0c;它两之间的区别是&#xff1a; Rect Transform多了&#xff1a;a.Pibot轴心点&#xff1b;b.Ancho…

002 学习鸿蒙应用开发ArkTs语言

目录 一.ArkTs语言介绍 1.ArkTs语言概述 2.ArkTs语言特性 二.基本UI描述 1.基本概念 2.UI描述规范 无参数构造配置 有参数构造配置 属性配置 事件配置 子组件配置 三.状态管理 1.基本概念 2.页面级状态管理 State Prop Link Observed和ObjectLink数据管理 P…

​从底层技术分析如何调教你的ChatGPT?

相信很多人都已经在使用类ChatGPT的工具进行工作或者娱乐了&#xff0c;这里说的类ChatGPT的是指和ChatGPT相同或者相似功能的产品&#xff0c;包括国外的开源平替模型、百度的文心一言等&#xff0c;但是你真的会使用这些工具和应用吗&#xff1f;你使用的方法是正确的吗&…

Java ---内部类

&#xff08;一&#xff09;定义 将一个类 A 定义在另一个类 B 里面&#xff0c;里面的那个类 A 就称为 内部类 &#xff08; InnerClass &#xff09; &#xff0c;类 B 则称为 外部类&#xff08; OuterClass &#xff09;。广泛意义上的内部类一般来说包括这四种&#xff1…

【中级软件设计师】—(针对上午题)软件工程上(三十五)

【中级软件设计师】—&#xff08;针对上午题&#xff09;软件工程&#xff08;三十五&#xff09; 一、CMM 1 2 3 4 5 二、能力成熟度模型集成&#xff08;CMMI&#xff09; 6 7 8 9 三、软件过程模型 &#xff08;一&#xff09;、瀑布模型 &#xff08;二&#xff09;、V模…

第八章 项目进度管理

项目进度有8个过程 1、规划项目&#xff0c;进度管理&#xff08;计划&#xff09; 2、定义活动&#xff08;活动清单&#xff09; 3、排序活动 4、估算活动资源&#xff08;估算人力&#xff09; 5、估算活动时间 6、制定进度计划表 7、控制进度 规划项目进度管理 为实施项目进…

薪资17K是一个怎样的水平?来看看98年测试工程师的面试全过程…

我的情况 大概介绍一下个人情况&#xff0c;男&#xff0c;本科&#xff0c;三年多测试工作经验&#xff0c;懂python&#xff0c;会写脚本&#xff0c;会selenium&#xff0c;会性能&#xff0c;然而到今天都没有收到一份offer&#xff01;从年后就开始准备简历&#xff0c;年…