栈和队列OJ题思路分享之括号匹配(C语言实现)

💓博主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);//初始化结构体
}
  1. 接下来我们先实现遇见左括号的情况:
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++;
        }
}

  1. 考虑了左括号后接下来是右括号:
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 程序就结束,这样写要简单一点


  1. 结合一下得出所有代码:
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💕

🔎 下期预告:用队列实现栈 🔍


相关推荐
运维佬1 小时前
CentOS 9 配置网卡
linux·centos
轩轩曲觞阁1 小时前
Linux网络——网络初识
linux·网络
2401_840192271 小时前
python基础大杂烩
linux·开发语言·python
weixin_438197382 小时前
K8S创建云主机配置docker仓库
linux·云原生·容器·eureka·kubernetes
舞动CPU8 小时前
linux c/c++最高效的计时方法
linux·运维·服务器
秦jh_10 小时前
【Linux】多线程(概念,控制)
linux·运维·前端
keep__go11 小时前
Linux 批量配置互信
linux·运维·服务器·数据库·shell
矛取矛求11 小时前
Linux中给普通账户一次性提权
linux·运维·服务器
Fanstay98511 小时前
在Linux中使用Nginx和Docker进行项目部署
linux·nginx·docker
大熊程序猿11 小时前
ubuntu 安装kafka-eagle
linux·ubuntu·kafka