数据结构习题——有效的括号(栈),栈与队列和互相实现,循环队列的实现

news2024/11/18 15:32:27

在这里插入图片描述

文章目录

  • 前言
  • 1、有效的括号
    • 题目
    • 思路
    • 代码
  • 2、用队列实现栈
    • 题目
    • 思路
    • 代码
  • 3、用栈实现对列
    • 题目
    • 思路
    • 代码
  • 4、设计循环队列
    • 4.1循环队列的概念和了解
    • 题目
    • 思路
    • 代码
  • 总结

前言

继上篇博客学习了栈与队列之后,今天我们来尝试着使用他们来写一些题目,话不多说,启动启动启动

1、有效的括号

习题链接:有效的括号

题目

在这里插入图片描述

思路

本题给定一个字符串,然后要在指定的条件下判断字符串是否有效
简而言之就是括号要对应起来且类型相同,不多不少刚刚好
想到昨天学习的栈,先进后出的规则,可以用到这里
遇到左括号入栈,遇到右括号就和栈顶元素匹配
如果最后栈内还有元素或者遍历字符串途中遇到括号不匹配直接返回false

代码

class Solution 
{
public:
    bool isValid(string s) 
    {
        char stack[10000];    //  定义一个字符数组,简易代表栈   
        int top = -1;
        for(int i = 0; s[i] !='\0'; ++i)    //  循环遍历字符串
        {
            char cur = s[i];
            if(cur == '(' || cur == '[' || cur == '{')    //  遇到左括号就入栈  
            {
                stack[++top] = cur;
            }
            else
            {
                if(top == -1)    //  如果遇到右括号   栈内无元素  ,直接返回false  
                {
                    return false;
                }
                char topcur = stack[top--];       //  取栈顶元素  
                if((topcur == '(' && cur != ')') || (topcur == '[' && cur != ']') || (topcur == '{' && cur != '}'))
                return false;    //   列出不匹配的情况  
            }
        }
        return top == -1;
    }
};

在这里插入图片描述

在上一篇的栈的具体学习过后,这个题目相对而言还是简单的,就是对栈的特殊结构的使用

2、用队列实现栈

习题链接:用队列实现栈

题目

在这里插入图片描述
在这里插入图片描述

思路

本题是仅且使用两个队列去实现一个先进后出的栈
要知道我们的队列是符合先进先出的特殊规则,要怎么才能实现栈呢?
我想到栈分为入栈和出栈还有取栈顶元素三个功能,我用一个队列来实现入栈,另外一个队列来实现出栈

上图
在这里插入图片描述
在这里插入图片描述
图片解析下,思路清晰明了
入栈就插入不为空的队列,出栈就把队列元素移动到空队列,只留下一个数据出队列就好了,取栈顶元素直接取不为空队列队尾元素即可。两个队列反复横跳。

小编这里还有另外一种思路,因为今天想偷一点小懒,使用stl库中的队列,这样就不用自己手写一个队列了。
一个队列作为主要队列,一个队列作为辅助队列,每次入栈插入辅助队列,然后把主要队列的元素一一插入辅助队列,这个时候,队头元素就是刚刚插入的数据,出栈就直接出队头元素即可,取队头元素也是一样的道理。

代码

class MyStack 
{
public:
    queue<int> q1;    //   本题偷了一点小懒   使用了stl库中的队列  它拥有昨天实现的队列的所有功能
    queue<int> q2;    //   q1为主要队列   q2为辅助队列  
    MyStack() {}
    void push(int x)    //  入栈  
    {
        q2.push(x);     // 将元素先push到  q2中   
        while(!q1.empty())     // q1不为空    
        {  
            q2.push(q1.front());      //  把q1队内的元素放入q2  
            q1.pop();				//  放入之后  q1 pop  
        }
        swap(q1,q2);    //  这个时候q1 是为空的  交换q1  q2  这个时候q1 的队头就是刚刚插入的数据   
    }
    int pop() 
    {
        int x = q1.front();   //  出栈操作   
        q1.pop();
        return x;
    }
    int top()     //  取栈顶元素   
    {
        return q1.front();
    }
    bool empty() 
    {
        return q1.empty();    
    }
};

每次插入都对队列进行一顿操作,相当于是给队列反过来变成栈了。
也是稳稳拿下了。
在这里插入图片描述

3、用栈实现对列

习题链接:用栈实现队列

题目

在这里插入图片描述

思路

有了上一题用队列实现栈的操作,想必也能想到用栈实现队列也大相径庭,就是用两个栈去把一个栈的特殊结构改变一下
也是构造两个栈,一个主要栈,一个辅助栈,每次入队就直接入辅助栈,等要出队列时,如果主要栈为空就把辅助栈的元素全部出栈,然后入到主要栈,这样元素顺序就颠倒了,也就是主要栈出栈就变成了出队。

代码

class MyQueue 
{
public:
    stack<int> s1;   //  构造主要栈和辅助栈  
    stack<int> s2;   
    MyQueue() {}  
    void push(int x) 
    {
        s1.push(x);   //  每次数据入队  入辅助栈  
    }
    int pop()    //  当要出队时  
    {
        if(s2.empty())   //  若此时主要栈为空  也就是意味着主要栈的元素已经全部出队了  
        {
            while(!s1.empty())   //   这个时候把辅助栈的元素出栈再入主要栈  主要栈的出栈顺序就是队列的出队顺序了  
            {
                s2.push(s1.top());
                s1.pop();
            }
        }
        int ans = s2.top();   //   如果主要栈还不为空   直接出栈即可  
        s2.pop();
        return ans;
    }
    int peek()    //   获取队头元素   
    {
        int ans = this->pop();   //  可以直接出队列  保存元素  再入栈  
        s2.push(ans);
        return ans;
    }
    bool empty() 
    {
        return s1.empty()&&s2.empty();   //  当连个栈都为空时  队列也为空  
    }
};

当对栈和队列的特性理解的深刻一点的时候,栈和队列的相互实现想想也是挺简单的,拿下拿下
在这里插入图片描述

4、设计循环队列

4.1循环队列的概念和了解

循环队列,环形队列⾸尾相连成环,环形队列可以使⽤数组实现,也可以使⽤循环链表实现

在这里插入图片描述

队列满的情况下,为什么 Q.rear 不存储数据?
为了能使⽤ Q.rear = Q.front 来区别是队空还是队满,我们常常认为出现上图b时的情况即为队满的情况
此时: rear+1=front

在这里插入图片描述
在这里插入图片描述
在用数组实现循环队列时,需要注意一点的是:当队列空间需要n个时,数组需要开n+1个容量
为什么呢?如果我现在只是按照队列的元素开指定个数组的空间 想想当队列为空的条件是什么 应该是 front == rear 吧 那当队列为满的情况呢 是不是也是 front == rear 这个时候就冲突了 ,不知道队列什么时候是空什么时候是满
所以我们这里是用数组的时候,开辟队列指定元素个数 n + 1个 。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上述图片数组开辟了 n+1和空间,这个时候队列为空和队列满的情况就不冲突了。需要注意的是在判断队列满的情况需要
(rear+1)%(capacity+1) ==front 我来解释一下 :数组此时容量是n+1,所以有一个空间是不储存数据的,也就是rear,当rear的下一个元素为front时,队列为满,这里%上容量大小是因为怕rear+1越界。

至于用链表实现循环队列,就是单向带头循环链表,相信大家已经滚瓜烂熟了,接下来,上题


习题链接:设计循环队列

题目

在这里插入图片描述

思路

本题就是设计一个循环队列,刚才已经带着大家把循环队列的概念已经了解透彻啦。
这里小编在写题就直接用c++啦,stl容器用起来还是很方便的,不要怕看不懂,我的注释是很详细的
话不多说,上代码

代码

class MyCircularQueue 
{
public:
    int front,rear,capacity;
    vector<int> arr;    //  这里类似于顺序表  开辟一个数组  arr
    MyCircularQueue(int k) 
    {
        capacity = k + 1;     //  定义capacity  为k + 1
        arr.assign(capacity,0);   //   这里类似于  给数组初始化全部为  0
        front = rear = 0;    //  然后  front  和   rear   都从数组下标0 开始 
    }    
 	bool isFull()     //  判断循环队列是否为满   
    {
        return (rear + 1) % capacity == front;   //  前面已经详细解释过啦   
    }
    bool enQueue(int value)     //  向循环队列插入元素   插入成功返回真  
    {
        if(isFull())    //  先判断队列是否为满   
        {
            return false;
        }
        arr[rear] = value;    //   不满就在  rear位置   插入数据即可  
        rear = (rear + 1) % capacity;   //  rear位置插入后  需要往后移动一步  这里还是要取模防止数组越界  
        return true;
    }
    
    bool isEmpty()    //  判断循环队列是否为空   
    {
        return front == rear;    //  直接返回判断条件    
    }
    
    bool deQueue()       //  向循环队列中删除一个元素   
    {
        if(isEmpty())    
        return false;
        front = (front + 1) % capacity;   //  如果队列不为空,直接让 front  往前走一步就好了   
        return true;
    }
    int Front()      //  获取队首元素    
    {
        if(isEmpty())    
        return -1;
        return arr[front];    //   队列不为空就直接返回   front位置对应的元素       
    }
    int Rear()     //  获取队尾元素   
    {
        if(isEmpty())
        return -1;
        return arr[(rear - 1 + capacity) % capacity];  //  因为rear位置是空缺不存储数据的 
        								//   所以要返回rear的前一个数据同时要防止数组越界的情况   
    }
};

到这里,循环队列的实现就结束啦,不出意外,还是拿下了。
在这里插入图片描述

总结

通过今天的习题,对栈和队列的理解更加深刻,同时也能熟练运用栈和队列,去互相实现还是挺有意思的
同时在写题的过程中不止对知识的掌握更加深刻,也让我学习到了新的知识——循环队列,还是挺有意思的。
好啦,栈和队列的内容就到这里啦,下一篇博客小编将为大家讲述新的知识
另外,有什么写的不好的或者不详细的还请大家指出来,谢谢大家

最后的最后,感谢大家能看到这里,我也是平平无奇的一枚在慢慢学习中的小趴菜,分享自己的学习经历,同时也能复习自己所学的知识。 小编持续跟新中…

芷兰生于深林,不以无人而不芳
每一行代码都是迈向更好的牛奶和面包的一步,加油加油加油

在这里插入图片描述

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

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

相关文章

Java连接MySQL(测试build path功能)

Java连接MySQL&#xff08;测试build path功能&#xff09; 实验说明下载MySQL的驱动jar包连接测试的Java代码 实验说明 要测试该情况&#xff0c;需要先安装好MySQL的环境&#xff0c;其实也可以通过测试最后提示的输出来判断build path是否成功&#xff0c;因为如果不成功会直…

计算机组成原理——高速缓存

标记表示——主存块号和缓存块之前的一一对应关系

Java面试之多线程并发篇(5)

前言 本来想着给自己放松一下&#xff0c;刷刷博客&#xff0c;突然被几道面试题难倒&#xff01;常用的线程池有哪些&#xff1f;简述一下你对线程池的理解&#xff1f;Java程序是如何执行的&#xff1f;锁的优化机制了解吗&#xff1f;说说进程和线程的区别&#xff1f;似乎…

JavaWeb之AJAX

前言 这一节讲JavaWeb之AJAX 1.概述 以前我们在servlet中得到数据&#xff0c;必须通过域给jsp&#xff0c;然后jsp在响应给浏览器 纯html不能获取servlet返回数据 所以我们用jsp 但是现在我们可以同AJAX给返回数据了 我们可以在sevlet中直接通过AJAX返回给浏览器 html中的J…

深入剖析String类的底层实现原理

嘿嘿,家人们,今天咱们来模拟实现string,好啦,废话不多讲,开干! 1:string.h 1.1:构造函数与拷贝构造函数 1.1.1:写法一 1.1.2:写法二(给缺省值) 1.2:赋值运算符重载与operatror[]获取元素 1.3:容量与迭代器 1.4:reserve与resize 1.5:清空与判断是否为空 1.6:push_back与…

【Go】-bufio库解读

目录 Reader和Writer接口 bufio.Reader/Writer 小结 其他函数-Peek、fill Reader小结 Writer Scanner结构体 缓冲区对于网络数据读写的重要性 Reader和Writer接口 在net/http包生成的Conn 接口的实例中有两个方法叫做Read和Write接口 type Conn interface {Read(b []b…

el-form el-table 前端排序+校验+行编辑

一、页面 <template><div class"bg" v-if"formData.mouldData?.length 0">当前暂无模板&#xff0c;点击<view class"add" click"addMould">立即创建</view></div><div v-else><el-col :x…

解决Docker环境变量的配置的通用方法

我们部署的很多服务都是以Docker容器的形式存在的。 在运行Docker容器前&#xff0c;除了设置网络、数据卷之外&#xff0c;还需要设置各种各样的环境变量。 有时候&#xff0c;由于容器版本的问题&#xff0c;一些文档没有及时更新&#xff0c;可能同时存在多个新旧版本的环…

使用win32com将ppt(x)文件转换为pdf文件

本文来记录下如何使用win32com将ppt(x)文件转换为pdf文件 文章目录 win32com概述win32com优缺点代码实例本文小结 win32com概述 Pywin32 是一个用于与 Microsoft Windows 操作系统交互的 Python 扩展模块&#xff0c;它提供了对多个 Windows API 的访问&#xff0c;包括对 Mic…

【nginx】client timed out和send_timeout的大小设置

websocket连接会断开&#xff0c;抓包检查后发现是中间的代理服务器nginx断开的&#xff0c;同时将后端和浏览器都断开了。将nginx日志调到debug级别后&#xff0c;有下面的断开信息。 [info] 125923#125923: *34 client timed out (110: Connection timed out) while proxyin…

代码段数据段的划分

DPL DPL存储在段描述符中&#xff0c;规定访问该段的权限级别(Descriptor Privilege Level) CPL CPL是当前进程的权限级别(Current Privilege Level)&#xff0c;是当前正在指向的代码段所在段的成绩&#xff0c;也就是CS段的DPL RPL RPL说明的是进程对段访问的请求权限(Re…

游戏引擎学习第14天

视频参考:https://www.bilibili.com/video/BV1iNUeYEEj4/ 1. 为什么关注内存管理&#xff1f; 内存分配是潜在的失败点&#xff1a; 每次进行内存分配&#xff08;malloc、new等&#xff09;时&#xff0c;都可能失败&#xff08;例如内存不足&#xff09;。这种失败会引入不稳…

基于Java Springboot电商个性化推荐系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

react中如何在一张图片上加一个灰色蒙层,并添加事件?

最终效果&#xff1a; 实现原理&#xff1a; 移动到图片上的时候&#xff0c;给img加一个伪类 &#xff01;&#xff01;此时就要地方要注意了&#xff0c;因为img标签是闭合的标签&#xff0c;无法直接添加 伪类&#xff08;::after&#xff09;&#xff0c;所以 我是在img外…

基于Java Springboot拍卖行系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

HTML5+CSS前端开发【保姆级教学】+前端介绍和软件安装

学习了基础编程刚刚开始学习计算机的程序员&#xff0c;你是否会这样的想法:前端和后端是什么呢&#xff1f;如果你是刚上大学的大一大二基础小白&#xff0c;但是身边的卷王同学已经超前知道之后要从事前后端开发了&#xff0c;并且在学习各种框架的课程&#xff0c;Aahhahah,…

Android Framework层介绍

文章目录 前言一、Android Framework 层概述二、主要组件1. 应用程序接口&#xff08;API&#xff09;2. 系统服务3. Binder4. 资源管理5. Content Provider6. 广播接收器&#xff08;BroadcastReceiver&#xff09;7. 服务&#xff08;Service&#xff09; 三、与 Linux Kerne…

【C++滑动窗口】1248. 统计「优美子数组」|1623

本文涉及的基础知识点 C算法&#xff1a;滑动窗口及双指针总结 LeetCode1248. 统计「优美子数组」 给你一个整数数组 nums 和一个整数 k。如果某个连续子数组中恰好有 k 个奇数数字&#xff0c;我们就认为这个子数组是「优美子数组」。 请返回这个数组中 「优美子数组」 的数…

【paper】分布式无人水下航行器围捕智能目标

An Effective Strategy for Distributed Unmanned Underwater Vehicles to Encircle and Capture Intelligent Targets2022.8IEEE TRANSACTIONS ON INDUSTRIAL ELECTRONICS【Q1 7.5】Mingzhi Chen 上海理工大学 Q1 Background&#xff1a;本文试图解决一个什么样的问题&#xf…

【更新中】《硬件架构的艺术》笔记(三):处理多个时钟

介绍 单时钟设计更易于实现&#xff0c;也更少出现亚稳态、建立和保持时间违例方面的问题。但在实践中&#xff0c;很少有设计只在一个时钟下运行。 多时钟域 多个始终可以有以下一种或多种时钟关系&#xff1a; 1、时钟频率不同。 2、时钟频率相同&#xff0c;但相位不同…