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

news2024/11/22 16:34:10

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:刷题分享⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你刷更多C语言和数据结构的题!
  🔝🔝

在这里插入图片描述


栈和队列刷题分享

  • 1. 前言🚦
  • 2. 括号匹配问题🚦
    • 2.1 审题🔴
    • 2.2 代码实现🔴
      • 2.21 导入栈🟠
      • 2.22 代码实现🟠
    • 2.3 代码优化🔴
      • 2.31 修改第一步🟠
      • 2.32 修改第二步🟠
  • 3. 总结🚦

1. 前言🚦

我们不久前给大家介绍了栈和队列这两种全新的结构,力扣上面有一些关于栈和队列的OJ题是非常经典的,这里我一共要给大家做三道题目的分享,分别是 1. 括号匹配问题: 力扣20题— 2. 用队列实现栈: 力扣225题— 3. 用栈实现队列: 力扣232题.今天这一章先分享第一个问题:括号匹配问题

🚫🚫🚫

如果你还没有自己实现过栈和队列,请跳转栈和队列详解,这里的题目需要使用自己实现的结构!


2. 括号匹配问题🚦

2.1 审题🔴

先看题:
在这里插入图片描述

首先这里需要注意的是,括号仅由’(‘,’[‘,’{',三对组成,并且一些复杂的形式比如:[({})],这种也是有效的括号,既然这个题出现在我们的栈和队列刷题中,那我也不卖关子,这个题是一道很经典的栈结构相关的题目,因为栈的这种先进先出的特殊结构,所以我们可以联想到, 当字符串中给的是左括号(不管是三个括号中的哪一种左括号)就入栈,然后,如果遇见右括号(不管是三个括号中哪一个右括号)就出栈匹配,看看左右能不能匹配上. 我们画个图来理解一下:

在这里插入图片描述
我们有了基本思路就可以开始上手了


2.2 代码实现🔴

2.21 导入栈🟠

我们已经明白这个题可以用栈来解答, 但是这个题没有给我们提供栈的结构,所以我们要把自己之前写过的栈导入到我们的题目当中: 具体操作请看下面视频:

怎么导入自己的栈


2.22 代码实现🟠

我们在实现栈的时候,没有在初始化函数中定义结构体,而是在test.c文件中初始化结构体的,所以第一步我们要先在题目中定义一下结构体并且将它初始化:

bool isValid(char * s)
{
    ST st;//定义一个结构体st(ST是我们自己命名的)
    StackInit(&st);//初始化结构体
}
  1. 接下来我们先实现遇见左括号的情况:
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. 考虑了左括号后接下来是右括号:
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. 结合一下得出所有代码:
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.并且值得注意的是,这里要是不仅仅是一个字符,要是是五个左括号没有右括号同样也要报错, 所以我们修改一下代码:

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.

并且这里栈为空分为几种情况:

  • 第一种: 字符串力压根儿没有左括号

  • 第二种: 字符串中右括号比左括号多,使得左括号全部出栈后还有右括号.

最终我们修改完后的代码:

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💕

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

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

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

相关文章

【密码学复习】第七章 公钥加密体制

公钥加密模型 密钥生成过程:接收消息的端系统(如图中的接收者Alice)产生一对密钥(PKA ,SKA ), PKA 是公开钥(用于加密), SKA 是秘密密钥(用于解密). 加密过程:Bob想向…

从C出发 30 --- 指针与堆空间

数组 就是变量的有序集,因此只有可以动态的创建一个变量,就可以动态的创建多个变量了, 堆空间就是一片内存区域,用于动态创建内存变量的区域 void 类型是基础类型,不是基础数据类型,为什么?因为…

MySQL --- 图形化工具DDL表结构操作

一. 图形化工具 1. 介绍 前面学习了DDL中关于数据库操作的SQL语句,在编写这些SQL时,都是在命令行当中完成的。在命令行当中来敲这些SQL语句很不方便,主要的原因有以下 3 点: 没有任何代码提示。(全靠记忆&#xff0…

行为型模式-备忘录模式

备忘录模式 概述 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,很多软件都提供了撤销(Undo&#xff0…

【自动化测试】Appium环境设置

启动Appium需要的环境配置有些复杂,这里将需要的环境配置整理出来,附上博主亲测有效的教程,有些教程有一点点老了,博主也做了备注,并且有些老一点步骤,博主根据现有的情况做了新的图文教程,大家…

近源渗透学习

一、近源渗透 近源渗透测试是网络空间安全领域逐渐兴起的一种新的安全评估手段。 它是一种集常规网络攻防、物理接近、社会工程学及无线电通信攻防等能力于一体的高规格网络安全评估行动。网络安全评估小组在签订渗透测试授权协议后,通过乔装、社工等方式实地物理侵…

微服务体系

目录 结构服务注册中心EurekaZookeeperConsul上面三者的对比 Ribbon 负载均衡负载均衡OpenFeign 远程服务调用Hystrix服务熔断常见的设置 Hystrix 工作流程Hystrix-DashBoard 的使用 SpringCloud Gateway核心工作流程 SpringCloud Config 分布式配置中心bootstrap.yml配置文件 …

独立按键识别

项目文件 文件 关于项目的内容知识点可以见专栏单片机原理及应用 的第四章 IO口编写 参考图电路编写程序,要求实现如下功能: 开始时LED均为熄灭状态,随后根据按键动作点亮相应LED(在按键释放后能继续保持该亮灯状态,直至新的按键压下时为止…

【实用工具】SpringBoot实现接口签名验证

需求场景 由于项目需要开发第三方接口给多个供应商,为保证Api接口的安全性,遂采用Api接口签名验证。 Api接口签名验证主要防御措施为以下几个: 请求发起时间得在限制范围内请求的用户是否真实存在是否存在重复请求请求参数是否被篡改 项目…

java8新特性——StreamAPI

1.集合处理数据的弊端 当我们在需要对集合中的元素进行操作的时候,除了必需的添加,删除,获取外,最典型的操作就是集合遍历。 package com.wxj.streamapi;import java.util.ArrayList; import java.util.Arrays; import java.uti…

E. Vasya and Good Sequences(异或)

Problem - E - Codeforces Vasya有一个由n个整数组成的序列a。 Vasya可以执行以下操作:从序列中选择一些数字,并交换其二进制表示中的任意一对位。例如,Vasya可以将数字6(… 000000001102)转换为3(… 00000…

[数据库系统] 一、外键约束 (educoder)

1.任务:给表添加外码。 2.相关知识 需要掌握: (1)什么是外码; (2)怎么给表添加外码。 (1)什么是外码 外部关键字 外码是另一张表中的主码。**外码的主要作用是保持数据的一致性,完整性。 如图有两张表,classId 是T…

蓝晓转02上市价格预测

蓝晓转02 基本信息 转债名称:蓝晓转02,评级:A,发行规模:5.460645亿元。 正股名称:蓝晓科技,今日收盘价:88.16元,转股价格:92.73元。 当前转股价值 转债面值 …

10.集合

1.泛型 1.1泛型概述 泛型的介绍 ​ 泛型是JDK5中引入的特性&#xff0c;它提供了编译时类型安全检测机制 泛型的好处 把运行时期的问题提前到了编译期间避免了强制类型转换 泛型的定义格式 <类型>: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如:…

深度学习模型部署的步骤和相关注意事项

文章目录 深度学习模型部署的步骤和相关注意事项什么是模型部署&#xff1f;步骤1&#xff1a;选择合适的部署环境步骤2&#xff1a;选择合适的部署框架步骤3&#xff1a;将模型转换为部署格式步骤4&#xff1a;创建API接口步骤5&#xff1a;部署模型总结 深度学习模型部署的步…

JWT漏洞基础

JWT漏洞基础 什么是JWTJWT漏洞介绍工具使用 身份认证(Authentication)又称鉴权&#xff0c;是指通过一定的手段&#xff0c;完成对用户身份的确认。认证的方式&#xff1a;sessioncookie、JWT、Token session认证的局限性 session认证机制需要配合cookie才能实现。由于cookie默…

极客时间- 数据结构与算法之美 - 王争 前 Google 工程师【学习笔记】

本文是 极客时间- 数据结构与算法之美 - 王争 前 Google 工程师。专栏学习笔记整理&#xff0c;课程链接&#xff1a;https://time.geekbang.org/column/intro/100017301?tabcatalog 01 | 为什么要学习数据结构和算法&#xff1f;面试业务开发工程师写出达到开源水平的框架才是…

大数据应用案例:如何在金融行业中利用数据挖掘实现风险控制和预测

引言 随着互联网和移动技术的发展&#xff0c;金融行业已经进入了数字化时代。大数据技术在金融行业的应用越来越广泛&#xff0c;其中最重要的应用就是风险控制和预测。本文将介绍如何利用数据挖掘技术在金融行业中实现风险控制和预测&#xff0c;以及一些成功的案例。 章节…

Android 系统的分区和文件系统(4)- Android 伪文件系统

声明 Android系统中有很多分区&#xff0c;每个分区内的文件系统一般都不同的&#xff0c;使用ADB进入系统/目录下可发现挂载这很多的目录&#xff0c;不同的目录中可来自不同的分区及文件系统&#xff1b;此篇参考了一些书籍及论文&#xff0c;仅供学习使用。只介绍大概理论&…

Valarrays

C标准库提供了一个class valarray用以进行数值数组的运算。 它声明于头文件<valarray> namespace std{template<class T> class valarray; //numeric array of type Tclass slice;template<class T> class slice_array; //slice out of a valarrayclass gs…