栈和队列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💕

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


相关推荐
2035去旅行3 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希1234 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡4 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.8 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道8 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.11 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落12 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨12 小时前
WSL2的安装与使用
linux·wsl
微小的鱼13 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng13 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器