💓博主CSDN主页:杭电码农-NEO💓
⏩专栏分类:刷题分享⏪
🚚代码仓库:NEO的学习日记🚚
🌹关注我🫵带你刷更多C语言和数据结构的题!
🔝🔝
栈和队列刷题分享
- [1. 前言🚦](#1. 前言🚦 "#1__14")
- [2. 括号匹配问题🚦](#2. 括号匹配问题🚦 "#2__22")
-
- [2.1 审题🔴](#2.1 审题🔴 "#21__23")
- [2.2 代码实现🔴](#2.2 代码实现🔴 "#22__34")
-
- [2.21 导入栈🟠](#2.21 导入栈🟠 "#221__35")
- [2.22 代码实现🟠](#2.22 代码实现🟠 "#222__45")
- [2.3 代码优化🔴](#2.3 代码优化🔴 "#23__133")
-
- [2.31 修改第一步🟠](#2.31 修改第一步🟠 "#231__134")
- [2.32 修改第二步🟠](#2.32 修改第二步🟠 "#232__178")
- [3. 总结🚦](#3. 总结🚦 "#3__233")
1. 前言🚦
我们不久前给大家介绍了栈和队列这两种全新的结构,力扣上面有一些关于栈和队列的OJ题是非常经典的,这里我一共要给大家做三道题目的分享,分别是 1. 括号匹配问题 : 力扣20题--- 2. 用队列实现栈: 力扣225题--- 3. 用栈实现队列: 力扣232题.今天这一章先分享第一个问题:括号匹配问题
🚫🚫🚫
如果你还没有自己实现过栈和队列,请跳转栈和队列详解,这里的题目需要使用自己实现的结构!
2. 括号匹配问题🚦
2.1 审题🔴
先看题:
首先这里需要注意的是,括号仅由'(','[','{',三对组成,并且一些复杂的形式比如:[({})],这种也是有效的括号,既然这个题出现在我们的栈和队列刷题中,那我也不卖关子,这个题是一道很经典的栈结构相关的题目,因为栈的这种先进先出的特殊结构,所以我们可以联想到, *当字符串中给的是左括号(不管是三个括号中的哪一种左括号)就入栈,然后,如果遇见右括号(不管是三个括号中哪一个右括号)就出栈匹配,看看左右能不能匹配上. *我们画个图来理解一下:
我们有了基本思路就可以开始上手了
2.2 代码实现🔴
2.21 导入栈🟠
我们已经明白这个题可以用栈来解答, 但是这个题没有给我们提供栈的结构,所以我们要把自己之前写过的栈导入到我们的题目当中: 具体操作请看下面视频:
怎么导入自己的栈
2.22 代码实现🟠
我们在实现栈的时候,没有在初始化函数中定义结构体,而是在test.c文件中初始化结构体的,所以第一步我们要先在题目中定义一下结构体并且将它初始化:
c
bool isValid(char * s)
{
ST st;//定义一个结构体st(ST是我们自己命名的)
StackInit(&st);//初始化结构体
}
- 接下来我们先实现遇见左括号的情况:
c
bool isValid(char * s)
{
ST st;
StackInit(&st);
int i=0;
while(s[i]!='\0')
{
if(s[i]=='('||s[i]=='['||s[i]=='{')//遇见左括号就入栈
{
StackPush(&st,s[i]);//这是我们自己实现的入栈函数
i++;
}
}
- 考虑了左括号后接下来是右括号:
c
else//遇见右括号了,出栈
{
STDataType top=StackTop(&st);//取出栈顶元素
StackPop(&st);//然后再将栈顶元素删除,使得栈顶的下一个元素到栈顶位置
if((s[i]==')'&&top!='(')||(s[i]==']'&&top!='[')||(s[i]=='}'&&top!='{'))
{
StackDestroy(&st);//每一次使用完栈结构都需要销毁
return false;//如果不匹配就返回假
}
else
{
i++;//如果匹配就接着往后走
}
}
. 这里需要注意的是,我们写 if 条件语句的时候,写的是不匹配的情况而不是匹配的情况,不匹配的情况就直接返回 false 程序就结束,这样写要简单一点
- 结合一下得出所有代码:
c
bool isValid(char * s)
{
ST st;
StackInit(&st);
int i=0;
while(s[i]!='\0')
{
if(s[i]=='('||s[i]=='['||s[i]=='{')
{
StackPush(&st,s[i]);
i++;
}
else//遇见右括号了,但是栈里面可能没有数据,说明前面没有左括号
{
STDataType top=StackTop(&st);
StackPop(&st);
if((s[i]==')'&&top!='(')||(s[i]==']'&&top!='[')||(s[i]=='}'&&top!='{'))
{
StackDestroy(&st);
return false;
}
else
{
i++;
}
}
}
return true;//如果整个过程都没有返回false,那么最后就返回true;
}
2.3 代码优化🔴
2.31 修改第一步🟠
当我们提交我们的代码时会发现一个错误:
这里我们的代码只通过了五个用例,*我们可以看见当字符串只有一个左括号时,我们压根没有进入我们的else语句当中,相当于我们把左括号入栈了之后,程序就结束了所以直接返回false.*并且值得注意的是,这里要是不仅仅是一个字符,要是是五个左括号没有右括号同样也要报错, 所以我们修改一下代码:
c
bool isValid(char * s)
{
ST st;
StackInit(&st);
int i=0;
while(s[i]!='\0')
{
if(s[i]=='('||s[i]=='['||s[i]=='{')
{
StackPush(&st,s[i]);
i++;
}
else
{
STDataType top=StackTop(&st);
StackPop(&st);
if((s[i]==')'&&top!='(')||(s[i]==']'&&top!='[')||(s[i]=='}'&&top!='{'))
{
StackDestroy(&st);
return false;
}
else
{
i++;
}
}
}
bool ret=StackEmpty(&st);//当栈里不为空时,证明还有左括号与右括号没有匹配
StackDestroy(&st);
return ret;
}
这里我们走完所有程序之后判断一下栈是否为空,假如不为空证明还有括号没有匹配上,我们的ret就等于false,就返回false,如果栈为空就返回true.
2.32 修改第二步🟠
当我们修改完第一步后提交代码又会遇见一个问题:
我们可以发现这里的报错和assertion有关,也就是我们之前实现栈时写的assert断言 ,它说ps->top fail了,再结合下面的用例:"]",我们可以推测出,当遇见右括号后我们要进行取栈顶数据这一个操作,可是这里没有左括号入栈,也就是栈里面为空,无法取出数据 (如果你不断言,这里可能是乱码 ),那这里我们又离成功近了一步 ,即我们在else语句执行之前,要判断栈是否为空,如果为空应该直接返回false.
并且这里栈为空分为几种情况:
- 第一种: 字符串力压根儿没有左括号
- 第二种: 字符串中右括号比左括号多,使得左括号全部出栈后还有右括号.
最终我们修改完后的代码:
c
bool isValid(char * s)
{
ST st;
StackInit(&st);
int i=0;
while(s[i]!='\0')
{
if(s[i]=='('||s[i]=='['||s[i]=='{')
{
StackPush(&st,s[i]);
i++;
}
else//遇见右括号了,但是栈里面可能没有数据,说明前面没有左括号
{
if(StackEmpty(&st))//如果栈为空就返回false
{
return false;
}
STDataType top=StackTop(&st);
StackPop(&st);
if((s[i]==')'&&top!='(')||(s[i]==']'&&top!='[')||(s[i]=='}'&&top!='{'))
{
return false;
}
else
{
i++;
}
}
}
bool ret=StackEmpty(&st);//栈为空证明左右括号已经匹配完了
StackDestroy(&st);
return ret;
}
3. 总结🚦
刷OJ题思考非常重要,先自己在脑子里过一遍有了大致思路再写代码会事半功倍,再一个,语句报错不要怕,不要觉得它是英文报错看不到就望而却步,使用翻译并且结合它下面给的用例来思考是哪个环节出了问题.
💕 我的码云:gitee-杭电码农-NEO💕
🔎 下期预告:用队列实现栈 🔍