栈和队列的经典例题,LeetCode 括号匹配问题;栈实现队列;队列实现栈;队列带环问题

1.前序

又有很久没有更新文章了,这次带你们手撕几道基础题;真的就和康纳吃饭一样简单!!!

如果还不会队列和栈的可以去看看之前写的博客; 栈的实现       队列概念以及实现  <- 快速传送

目录

1.前序

2.括号匹配问题,有效的括号 <- 快速传送

3.用队列实现栈   <- 快速传送

3.1 核心思路

3.2代码部分,上面是思路

4.用栈实现队列  <- 快速跳转

4.1这里用c语言实现的所以要复制一个栈

5.带环队列 <- 快速跳转


2.括号匹配问题,有效的括号 <- 快速传送

  1. 核心思路:
    1. 一定是左括号入栈,右括号在外面
    2. 入完数据尝试匹配,不相等 可以,如果相等可以走到最后返回true
    3. 左括号有数据;右括号没数据;此时说明返回false
    4. 右括号有数据;左括号没有;右括号还有没匹配的,此时*s有数据进了循环,if判断栈为NULL此时为false

  1. 根据上图分析,有4种情况
  2. 第一步,建立循环有数据就往下读取,左括号入栈,右括号不如栈,进入的数据拿去比对
  3. 先处理正常情况,没有进入到if判断(不匹配的情况),此时就可以证明时匹配上了,因为没有返回false
  4. 注意:不匹配的情况;当满足左括号和右括号对应的时候,此时就可以不会进if
bool isValid(char* s) {ST str;STInit(&str);while(*s)//有数据就继续读{if(*s == '(' || *s == '{' || *s == '[')//是左括号就入栈{STPush(&str,*s);}else//尝试和右括号匹配{//为 0 时返回 true,然后执行if,返回false,匹配失败if(STEmpty(&str))//经过前面的匹配后,此时栈为NULL了,但是*s 还有数据{STDestroy(&str);return false;}char top = STTop(&str);//不管取没取到,先Pop,如果匹配成功就正常往下走STPop(&str);//不匹配的情况,不匹配直接返回if(top == '(' && *s != ')' ||top == '[' && *s != ']' ||top == '{' && *s != '}'){//销毁空间,并返回STDestroy(&str);return false;}}s++;//找下一个元素}//返回值为false说明有栈内有数据,但是前面while已经结束,没有字符可以匹配了//意味着左括号比右括号的多 ,只要不匹配就返回falsebool ret = STEmpty(&str);STDestroy(&str);return ret;//正常返回
}

3.用队列实现栈   <- 快速传送

  1. 传参部分要注意,这个MyStack结构体里装着两个队列
  2. 这里要传&(que->q1)或者&que->q1,因为这是两个结构体,改变结构体需要结构体指针
  3. Create部分,首先需要给MyStack(匿名结构体)开辟空间,这里他让我们初始化两个队列,并且完成初始化,这部分就直接调用函数即可。

3.1 核心思路

核心思路:插入数据时始终插入到有数据的队列去;始终要空出一个队列,用来删除

  1. Push,实现栈的后进后出,第一次开始数据随便放,后面插入数据要放到有数据后
    1. QueueEmpty,这个函数为NULL返回true(表示没有数据),反之返回false,说明此时有数据;
    2. 注意:!取反,将结果取反,此代码中有数据返回false取反后得到true
  2. Pop,这里利用假设法;先假设q1有数据,假设失败那就是q2,这里的if判断同样用判空来判断是否有数据
    1. 这里while里面就是挪动数据了 ,此时你需要取到头元素,挪动size - 1个数据,留一个在que1里面pop掉,就模拟了栈的出栈
    2. QueuePop(NoEmpty);//只是被导到Empty,原空间还有数据,所以要Pop掉已经导过去的数据
    3. 这里根据题目要求,要保存数据,然后要pop掉这块空间,最后返回该值

  1. Top,取栈的top元素,也就是队列的尾元素,当然这个尾元素也是需要看,数据在哪一边,同样的配方,判NULL
  2. Empty栈的判NULL,竟然是由两个队列组成自然也就需要,两个都为NULL才行,&& 也是运算符;同时为NULL,返回true
  3. 这里的free,要了解结构体,开始初始化是什么,你就怎么销毁;
  4. 这里销毁时候先后顺序的,不能直接销毁obj,而是要先销毁obj里面两个的q1和q2才行

3.2代码部分,上面是思路

typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* que = (MyStack*)malloc(sizeof(MyStack));QueueInit(&(que->q1));//通过结构体指针访问到q1,用初始化函数直接初始化QueueInit(&(que->q2));return que;
}void myStackPush(MyStack* obj, int x) {//obj 是装着q1 和 q2两个结构体的//分为两种情况,那个后面有数据有往哪里放,都没有随便放一个if(!QueueEmpty(&(obj->q1)))//如果q1这个队列有数据,返回false,! 取反后true,执行if{QueuePush(&(obj->q1),x);}//obj->q2有数据,或者都没有else{QueuePush(&(obj->q2),x);}
}
int myStackPop(MyStack* obj) {//假设法,因为当一方成立是,双方代码一样Queue* Empty = &(obj->q1);//假设p1没数据 Queue* NoEmpty = &(obj->q2);//有数据if(!QueueEmpty(&(obj->q1)))//非NULL,有数据;假设失败{Empty = &(obj->q2);NoEmpty = &(obj->q1);}while(QueueSize(NoEmpty) > 1)//有数据的一方需要导到无数据的一方,个数size - 1{QueuePush(Empty,QueueFront(NoEmpty));//取到有数据的队头,导到无数据的一方QueuePop(NoEmpty);//只是被导到Empty,原空间还有数据,所以要Pop掉已经导过去的数据}QuDataType ret = QueueFront(NoEmpty);QueuePop(NoEmpty);return ret;
}int myStackTop(MyStack* obj) {if(!QueueEmpty(&(obj->q1)))//此时q1有数据,直接取到队列的队尾{return QueueBack(&(obj->q1));}else{return QueueBack(&(obj->q2));}
}bool myStackEmpty(MyStack* obj) {
//只有这两个队列同时为NULL,才说明没数据了;满足两个判空都为NULL,才会返回true,&&也相当于是运算符return QueueEmpty(&(obj->q1)) && QueueEmpty(&(obj->q2));
}void myStackFree(MyStack* obj) {QueueDestroy(&(obj->q1));//首先要free掉q1和q2 这两个队列,然后才是objQueueDestroy(&(obj->q2));free(obj);
}

4.用栈实现队列  <- 快速跳转

  1. 此题创建两个栈来实现,stpush只入数据,相当于入队;stpop只出数据,相当于出队
  2. Create,首先是初始化MyQueue 里面放上两个栈,栈也初始化;
  3. Push;push数据那么调用栈的push函数即可;注意:STPush只用来放数据
  4. Peek,返回开头元素;把数据都导到stpop这样刚好压栈的元素就在栈顶;
    1. 要让这里的stpop没有数据才能导入进去只要stpop有数据就不要进
    2. 因为要始终保持队列的先进先出,假如stpush的数据导过来不就乱了
    3. 如果没进if说明有数据,那就不要导到stpop了
  5. 这里用动图说明原因;只有stpop数据出完才进数据

  1. Pop,删除队列开头的数据并返回元素;这里为什么调用一下myQueuePeek函数呢?
    1. 因为我们拿数据始终在stpop拿;那么stpop没数据自然要!!!
    2. 有了数据直接取头元素,删除返回即可
  2. Empty;判断是为NULL,因为这个是模拟是队列的功能;所以两个都要为NULL
  3. Free;怎么申请的空间,怎么倒着销毁;和队列实现栈的销毁逻辑一样

4.1这里用c语言实现的所以要复制一个栈

typedef struct {ST stpush;//入队ST stpop;//出队
} MyQueue;MyQueue* myQueueCreate() {MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));STInit(&(obj->stpush));STInit(&(obj->stpop));return obj;
}void myQueuePush(MyQueue* obj, int x) {STPush(&(obj->stpush),x);//stpush只入数据
}int myQueuePeek(MyQueue* obj) {if(STEmpty(&(obj->stpop)))//pop这边栈没数据就要导入数据{while(!STEmpty(&(obj->stpush)))//push有数据就到导{int top = STTop(&(obj->stpush));STPush(&(obj->stpop),top);STPop(&(obj->stpush));//数据挪到那边就要删除了}}return STTop(&(obj->stpop));
}
int myQueuePop(MyQueue* obj) {int front = myQueuePeek(obj);//stpop这边有数据才能删,如果不用调整刚好也拿到了STPop(&(obj->stpop));return front;
}bool myQueueEmpty(MyQueue* obj) {return STEmpty(&(obj->stpush)) && STEmpty(&(obj->stpop));//两个都为NULL才为NULL
}void myQueueFree(MyQueue* obj) {STDestroy(&(obj->stpush));STDestroy(&(obj->stpop));free(obj);
}

5.带环队列 <- 快速跳转

  1. Create,这个部分就是初始化了,需要开辟两个空间,一个是MyCircularQueue结构体的另外一个就是arr 数组的
  2. IsEmpty,判NULL

  1. 多开一块空间的意义是,防止head ==tail时,不知道是满还是NULL
  2. IsFull,判满

  1. EnQueue,向循环队列插入一个元素;在开始之前肯定要判断是否为满,满了就不能插入了

  1. DeQueue,从循环队列中删除一个元素;在开始之前要判NULL,不然你删个屁

  1. Front;开始之前肯定要判NULL;head位置的数据没啥问题直接取到就行,特殊情况在tail,因为指向下一个
  2. Rear,取尾的数据;普通情况正常取;特殊情况就是有效数据正好是最后一个,当tail指向下一个位置(也就是下标0);

typedef struct {int* arr;int head;int tail;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* Cqueue = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));if(Cqueue == NULL){perror("malloc Cqueuq");return 0;}//多开辟一个空间防止假溢出,这里不需要临时变量,也和数据丢不丢是没关系Cqueue->arr = (int*)malloc(sizeof(int) * (k + 1));Cqueue->head = Cqueue->tail = 0;//刚开始都指向下标0Cqueue->k = k;return Cqueue;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->head == obj->tail;//判断当前存储的位置是否为NULL
}bool myCircularQueueIsFull(MyCircularQueue* obj) {return ((obj->tail + 1) % (obj->k + 1)) == obj->head;//满了返回true
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj))//判满return false;obj->arr[obj->tail] = value;obj->tail++;obj->tail %= (obj->k + 1);return true;  
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))//判NULLreturn false;obj->head++;obj->head %= (obj->k + 1);return true;
}int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->arr[obj->head];//取当前数据
}int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->arr[(obj->tail - 1 + obj->k + 1) % (obj->k + 1)];
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->arr);free(obj);
}
  1. free,空间的销毁就是,怎么申请怎么销毁;假如先申请的obj后申请的obj->arr;那么就反着销毁

总结;

  1. 最近改变了一下学习方式;上完课要及时写作业,而且要独立完成效果最好
  2. 反正都这么菜了,多进步一点也算好的;总之不能止步不前

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jmeter例题分析-作业一

作业 作业1概要 本文档是关于执行软件性能测试的详细指南&#xff0c;包括使用JMeter工具进行测试的步骤和要求。 文档分为两个主要部分&#xff1a;性能测试的执行和性能测试报告的编写。 在第一部分中&#xff0c;详细描述了如何使用 JMeter进行性能测试。这包括设置测试环…

【机器学习】大模型在机器学习中的应用:从深度学习到生成式人工智能的演进

&#x1f512;文章目录&#xff1a; &#x1f4a5;1.引言 ☔2.大模型概述 &#x1f6b2;3.大模型在深度学习中的应用 &#x1f6f4;4.大模型在生成式人工智能中的应用 &#x1f44a;5.大模型的挑战与未来展望 &#x1f4a5;1.引言 随着数据量的爆炸性增长和计算能力的提…

LeetCode //C - 119. Pascal‘s Triangle II

119. Pascal’s Triangle II Given an integer rowIndex, return the rowIndexth (0-indexed) row of the Pascal’s triangle. In Pascal’s triangle, each number is the sum of the two numbers directly above it as shown: Example 1: Input: rowIndex 3 Output: …

Autodesk 3DS Max v2025 解锁版安装教程 (3D 建模软件)

前言 Autodesk 3ds Max 是一款功能强大的 3D 建模和动画解决方案&#xff0c;游戏开发人员、视觉效果艺术家和平面设计师使用它来创建庞大的世界、令人惊叹的场景和引人入胜的虚拟现实 (VR) 体验。 Autodesk 3DS MAX是业界使用最广泛的3D建模和动画软件程序之一&#xff0c;它…

6.小程序页面布局 - 账单明细

文章目录 1. 6.小程序页面布局 - 账单明细1.1. 竞品1.2. 布局分析1.3. 布局demo1.4. 页面实现-头部1.5. 账单明细1.5.1. 账单明细-竞品分析1.5.2. 账单明细-实现1.5.2.1. 账单明细-实现-mock数据1.5.2.2. 每日收支数据的聚合整理1.5.2.3. 页面scroll-view 1.6. TODO 1. 6.小程序…

力扣HOT100 - 72. 编辑距离

解题思路&#xff1a; 动态规划 class Solution {public int minDistance(String word1, String word2) {int n1 word1.length();int n2 word2.length();int[][] dp new int[n1 1][n2 1];for (int j 1; j < n2; j) dp[0][j] dp[0][j - 1] 1;for (int i 1; i < …

OA界面这么香吗?总有老铁私信,让我多发点,他好参考。

OA的确是B端系统应用最为广泛的一种&#xff0c;这次再给大家分享十来个页面&#xff0c;希望对他们的界面提升有所帮助。 举报 评论 3

【数据结构与算法】之堆的应用——堆排序及Top_K问题!

目录 1、堆排序 2、Top_K问题 3、完结散花 个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 1、堆排序 对一个无序的数组…

焦化超低排平台选哪家好?(已解答)

在环保政策日益严格的背景下&#xff0c;焦化行业的超低排放改造成为企业转型升级的必经之路。朗观视觉小编建议&#xff0c;选择合适的焦化超低排平台对于确保改造效果和实现可持续发展具有重要意义。本文将从多个维度为您提供一份全面的评估与选择指南&#xff0c;帮助您在众…

【计算机毕业设计】030英语学习交流平台微信小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Volatile的内存语义

1、volatile的特性 可见性&#xff1a;对一个volatile变量的读&#xff0c;总能够看到任意一个线程对这个volatile变量的写入。 原子性&#xff1a;对任意单个volatile变量的读/写具有原子性&#xff0c;但类似于volatile这种复合操作不具有原子性。 接下来我们用程序验证。…

Spring Cloud 系列之Gateway:(9)初识网关

传送门 Spring Cloud Alibaba系列之nacos&#xff1a;(1)安装 Spring Cloud Alibaba系列之nacos&#xff1a;(2)单机模式支持mysql Spring Cloud Alibaba系列之nacos&#xff1a;(3)服务注册发现 Spring Cloud 系列之OpenFeign&#xff1a;(4)集成OpenFeign Spring Cloud …

【2024软考】史上最全!软考刷题+解析大合集(9万字全手工打,货真价实)

计算机基础知识 1.中断向量表用来保存各个中断源的中断服务程序的入口地址。当外设发出中断请求信号&#xff08;INTR&#xff09;以后&#xff0c;由中断控制器&#xff08;INTC&#xff09;确定其中断号&#xff0c;并根据中断号查找中断向量表来取得其中断服务程序的入口地…

89.网络游戏逆向分析与漏洞攻防-游戏技能系统分析-游戏中使用的哈希算法逆向分析

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

HMI设计:再谈上位机与下位机,附海量案例图

上期回顾&#xff1a;HMI界面之&#xff1a;上位机界面设计&#xff0c;一文扫盲 一、上位机负责控制和决策&#xff0c;下位机负责采集和执行 上位机和下位机是两个概念&#xff0c;通常用于描述计算机系统中不同层次的设备或组件。 上位机&#xff08;Host Computer&#x…

kubernetes之prometheus kube-controller-manager。 scheduler报错问题

项目场景&#xff1a; prometheus scheduler及kube-controller-manager监控报错 问题描述 kubeadm搭建完kube-prometheus 会有这个报错 原因分析&#xff1a; rootmaster2:~# kubectl describe servicemonitor -n kube-system kube-controller-manager通过以上图片我们发现 k…

解决GoLand无法Debug

goland 调试的的时候提示如下错误 WARNING: undefined behavior - version of Delve is too old for Go version 1.22.3 (maximum supported v 其实个原因是因为正在使用的Delve调试器版本太旧&#xff0c;无法兼容当前的Go语言版本1.22.3。Delve是Go语言的一个调试工具&#…

【vue-5】双向数据绑定v-model及修饰符

单向数据绑定&#xff1a;当数据发生改变时&#xff0c;视图会自动更新&#xff0c;但当用户手动更改input的值&#xff0c;数据不会自动更新&#xff1b; 双向数据绑定&#xff1a;当数据发生改变时&#xff0c;视图会自动更新&#xff0c;但当用户手动更改input的值&#xf…

好用的window粘贴板

可以设置指定的快捷键&#xff0c;在需要使用最近复制的记录时快速的复用 -> Ditto。 选择Download即可 地址&#xff1a;Ditto clipboard manager (sourceforge.io)https://ditto-cp.sourceforge.io/

IOS开发者证书快捷申请

App Uploader 在进行iOS应用开发中,可以借助appuploader辅助工具进行证书制作、上传和安装测试等操作。首先,您需要访问官方网站获取最新版本的appuploader。最新版本已经优化了与Apple账号的登录流程,无需支付688元,并提供了Windows版和Mac版供用户选择。下载完成后,解压…