【数据结构】栈 与【LeetCode】20.有效的括号详解

news2025/4/5 0:22:52

目录

  • 一、栈
    • 1、栈的概念及结构
    • 2、栈的实现
    • 3、初始化栈和销毁栈
    • 4、打印栈的数据
    • 5、入栈操作---栈顶
    • 6、出栈---栈顶
      • 6.1栈是否为空
      • 6.2出栈---栈顶
    • 7、取栈顶元素
    • 8、获取栈中有效的元素个数
  • 二、栈的相关练习
    • 1、练习
    • 2、AC代码

个人主页,点这里~
数据结构专栏,点这里~

在这里插入图片描述

一、栈

1、栈的概念及结构

:⼀种特殊的线性表,其只允许在固定的⼀端进行元素的插入和删除元素操作。进行数据插入和删除操作的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈入数据在栈顶
出栈:栈的删除操作叫做出栈出数据也在栈顶
在这里插入图片描述
以上这张图片很好的反映了栈的结构,及出入栈的顺序。

2、栈的实现

栈的实现⼀般可以使用数组或者链表实现,相对而言数组的结构实现更优⼀些。因为数组在尾上插入,数据的代价比较小。数组在尾上插入整型数据只需要增加4个字节,但链表增加的字节就大的多了

typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;     //指向栈顶位置
	int capacity;//数据容量
}ST;

3、初始化栈和销毁栈

我们已经知道用什么方法实现栈,并且已经将栈的结构写出来了,接下来就该初始化了。
初始化:

void StackInit(ST* ps)
{
	ps->arr = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

初始化栈十分简单,只需把arr数组置为空,栈顶top和容量capacity置为0即可。

销毁:

void StackDestroy(ST* ps)
{
	if (ps->arr)//如果不为NULL
	{
		ps->arr = NULL;
	}
	ps->top = ps->capacity = 0;
}

以上就是栈的初始化以及销毁的代码了,和我们讲顺序表的时候差不多。

4、打印栈的数据

void SPrint(ST* ps)
{
	assert(ps);
	for (int i = 0;i < ps->top;i++)
	{
		printf("%d", ps->arr[i]);
		if (i < ps->top - 1)
		{
			printf("->");
		}
	}
}

5、入栈操作—栈顶

我们知道栈只能从栈顶入数据和出数据,所以我们就大概知道如何入栈了。

//入栈---栈顶
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)//如果栈空间满了就增容
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps -> capacity;
		STDataType* set = (STDataType*)realloc(ps->arr,sizeof(STDataType) * newcapacity);
		if (set == NULL)
		{
			perror("realloc fail!");
			return 1;
		}
		ps->arr = set;
		ps->capacity = newcapacity;
	}
	ps->arr[ps->top++] = x;
}

以上是入栈的代码,但在入栈之前呢,我们要考虑栈空间是不是满了,也就是栈顶是不是和容量一样大,如果满了,我们需要增容,在进行增容之前,我们还要考虑topcapacity是不是都为0,如果为0的话,我们要把容量大小置为4,否则的话容量扩大为二倍。

测试代码:

#include "Stack.h"

void test()
{
	ST plist;
	StackInit(&plist);
	StackPush(&plist, 1);
	StackPush(&plist, 2);
	StackPush(&plist, 3);
	SPrint(&plist);
}

int main()
{
	test();

	return 0;
}

测试结果
在这里插入图片描述

6、出栈—栈顶

在实现出栈之前我们要考虑栈里面的元素是否为空,如果为空就终止操作,所以我们先写一个判空函数,这样我们就可以在出栈之前知道栈是否为空了。

6.1栈是否为空

bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

这里用到了bool类型记得要加上#include<stdbool.h>头文件。

6.2出栈—栈顶

void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	ps->top--;
}

这里实现出栈是只需要实现top减一即可,因为我们不会访问top之后的元素。

7、取栈顶元素

STDataType StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}

这里取栈顶元素时,我们只需要判断一下栈是否为空,再将栈顶元素返回即可。

8、获取栈中有效的元素个数

int StackSize(ST* ps)
{
	return ps->top;
}

以上就是栈的常见操作,接下来让我们做一道练习题试一下吧!

二、栈的相关练习

1、练习

题目描述:
在这里插入图片描述
题目链接,点击这里~

没有做过的,可以先看题目思考一下,下面会给出题解。

我们根据题目描述可以知道题目让我们判断括号匹配是否正确,如果正确返回true,如果错误返回false
我们在利用栈思想(先进后出)进行求解的时候,可以当遇到左括号让它入栈,然后再遇到右括号的时候让栈顶的和它匹配(在括号匹配的情况下,最后出现的左括号总与最先出现的右括号匹配),如果不匹配就一定是非法的,返回false,如果都匹配的话就是合法的,返回true这里可以用数组模拟栈。我们在遇到左括号例如'('时我们可以在栈中保存')',这样在比较的时候容易比较。

  • 特殊情况一:
    字符数目是奇数,只要是奇数就一定不匹配,直接返回false
    int len=strlen(s);
    if(len%2==1)
    {
        return false;
    }
  • 特殊情况二:
    如果全是左括号,那么最后栈顶top一定大于0,而如果是正确匹配的情况下,到最后top肯定是0。因为我们初始化top0。所以遇到top大于0的情况直接返回false
    //到最后top大于0的情况
    if(top>0)
    {
        return false;
    }
  • 如果全是右括号,那么在比较的时候,top一定为0,此时栈中没有元素,也就无法比较,所以遇到比较时top0的情况也直接返回false
            if(top==0||s[i]!=stack[--top])
            {
                return false;
            }

2、AC代码

AC代码:

bool isValid(char* s) 
{
    int len=strlen(s);
    if(len%2==1)
    {
        return false;
    }
    char stack[10005];
    int top=0;
    int i;
    for(i=0;i<len;i++)
    {
        if(s[i]=='(')
        {
            stack[top++]=')';
        }
        else if(s[i]=='[')
        {
            stack[top++]=']';
        }
        else if(s[i]=='{')
        {
            stack[top++]='}';
        }
        else
        {
            if(top==0||s[i]!=stack[--top])
            {
                return false;
            }
        }
    }
    if(top>0)
    {
        return false;
    }
    return true;
}

总结:
以上就是本期博客分享的全部内容啦!如果觉得文章还不错的话可以三连支持一下,你的支持就是我前进最大的动力!
技术的探索永无止境! 道阻且长,行则将至!后续我会给大家带来更多优质博客内容,欢迎关注我的CSDN账号,我们一同成长!
(~ ̄▽ ̄)~

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

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

相关文章

Redis设计与实现-哨兵

哨兵模式 1、启动并初始化sentinel1.1 初始化服务器1.2 使用Sentinel代码1.3 初始化sentinel状态1.4 初始化sentinel状态的master属性1.5 创建连向主服务器的网络连接 2、获取主服务器信息3、获取从服务器的信息4、向主从服务器发送信息5、接受主从服务器的频道信息6、检测主观…

C++进阶——封装哈希表实现unordered_map/set

与红黑树封装map/set基本相似&#xff0c;只是unordered_map/set是单向迭代器&#xff0c;模板多传一个HashFunc。 目录 1、源码及框架分析 2、模拟实现unordered_map/set 2.1 复用的哈希表框架及Insert 2.2 iterator的实现 2.2.1 iteartor的核心源码 2.2.2 iterator的实…

【算法day25】 最长有效括号——给你一个只包含 ‘(‘ 和 ‘)‘ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

32. 最长有效括号 给你一个只包含 ‘(’ 和 ‘)’ 的字符串&#xff0c;找出最长有效&#xff08;格式正确且连续&#xff09;括号子串的长度。 https://leetcode.cn/problems/longest-valid-parentheses/ 2.方法二&#xff1a;栈 class Solution { public:int longestValid…

Jenkins + CICD流程一键自动部署Vue前端项目(保姆级)

git仓库地址&#xff1a;参考以下代码完成,或者采用自己的代码。 南泽/cicd-test 拉取项目代码到本地 使用云服务器或虚拟机采用docker部署jenkins 安装docker过程省略 采用docker部署jenkins&#xff0c;注意这里的命令&#xff0c;一定要映射docker路径&#xff0c;否则无…

一款超级好用且开源免费的数据可视化工具——Superset

认识Superset 数字经济、数字化转型、大数据等等依旧是如今火热的领域&#xff0c;数据工作有一个重要的环节就是数据可视化。 看得见的数据才更有价值&#xff01; 现如今依旧有多数企业号称有多少多少数据&#xff0c;然而如果这些数据只是呆在冷冰冰的数据库或文件内则毫无…

RedHatLinux(2025.3.22)

1、创建/www目录&#xff0c;在/www目录下新建name和https目录&#xff0c;在name和https目录下分别创建一个index.htm1文件&#xff0c;name下面的index.html 文件中包含当前主机的主机名&#xff0c;https目录下的index.htm1文件中包含当前主机的ip地址。 &#xff08;1&…

【C++篇】类与对象(上篇):从面向过程到面向对象的跨越

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对C感兴趣的…

智慧运维平台:赋能未来,开启高效运维新时代

在当今数字化浪潮下&#xff0c;企业IT基础设施、工业设备及智慧城市系统的复杂度与日俱增&#xff0c;传统人工运维方式已难以满足高效、精准、智能的管理需求。停机故障、低效响应、数据孤岛等问题直接影响企业运营效率和成本控制。大型智慧运维平台&#xff08;AIOps, Smart…

基于大语言模型的智能音乐创作系统——从推荐到生成

一、引言&#xff1a;当AI成为音乐创作伙伴 2023年&#xff0c;一款由大语言模型&#xff08;LLM&#xff09;生成的钢琴曲《量子交响曲》在Spotify冲上热搜&#xff0c;引发音乐界震动。传统音乐创作需要数年专业训练&#xff0c;而现代AI技术正在打破这一壁垒。本文提出一种…

Reactive编程:什么是Reactive编程?Reactive编程思想

文章目录 **1. Reactive编程概述****1.1 什么是Reactive编程&#xff1f;****1.1.1 Reactive编程的定义****1.1.2 Reactive编程的历史****1.1.3 Reactive编程的应用场景****1.1.4 Reactive编程的优势** **1.2 Reactive编程的核心思想****1.2.1 响应式&#xff08;Reactive&…

深度剖析:U盘突然无法访问的数据拯救之道

一、引言 在数字化办公与数据存储日益普及的当下&#xff0c;U盘凭借其小巧便携、即插即用的特性&#xff0c;成为了人们工作、学习和生活中不可或缺的数据存储工具。然而&#xff0c;U盘突然无法访问这一棘手问题却时常困扰着广大用户&#xff0c;它不仅可能导致重要数据的丢失…

蓝桥杯-特殊的三角形(dfs/枚举/前缀和)

思路分析 深度优先搜索&#xff08;DFS&#xff09;思路 定义与参数说明 dfs 函数中&#xff0c;last 记录上一条边的长度&#xff0c;用于保证新选边长度大于上一条边&#xff0c;实现三边互不相等 。cnt 记录已选边的数量&#xff0c;当 cnt 达到 3 时&#xff0c;就构成了…

一文详解k8s体系架构知识

0.云原生 1.k8s概念 1. k8s集群的两种管理角色 Master&#xff1a;集群控制节点&#xff0c;负责具体命令的执行过程。master节点通常会占用一股独立的服务器&#xff08;高可用部署建议用3台服务器&#xff09;&#xff0c;是整个集群的首脑。 Master节点一组关键进程&#xf…

wx162基于springboot+vue+uniapp的在线办公小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

Baklib内容中台的核心优势是什么?

智能化知识管理引擎 Baklib的智能化知识管理引擎通过多源数据整合与智能分类技术&#xff0c;实现企业知识资产的自动化归集与动态更新。系统内置的语义分析算法可自动识别文档主题&#xff0c;结合自然语言处理技术生成结构化标签体系&#xff0c;大幅降低人工标注成本。针对…

【C++】C++11介绍列表初始化右值引用和移动语义

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. C11简介2. 统一的列表初始化2.1&#xff5b;&#xff5d;初始化2.2 std::initializer_list 3. 声明3.1 auto3.2 decltype3.3 nullptr 4. 范围for循环4.1 范围for的语法4.2 范围for的使用条件 5. STL中一些变化6. 右…

搜广推校招面经六十一

美团推荐算法 一、ANN算法了解么&#xff1f;说几种你了解的ANN算法 ANN 近似最近邻搜索&#xff08;Approximate Nearest Neighbor Search&#xff09;算法 1.1. KD-Tree&#xff08;K-Dimensional Tree&#xff0c;K 维树&#xff09; 类型: 空间划分数据结构适用场景: 低…

人工智能与软件工程结合的发展趋势

AI与软件工程的结合正在深刻改变软件开发的流程、工具和方法&#xff0c;其发展方向涵盖了从代码生成到系统维护的整个生命周期。以下是主要的发展方向和技术趋势&#xff1a; 1. 软件架构体系的重构 从“面向过程”到“面向目标”的架构转型&#xff1a; AI驱动软件设计以目标…

nacos 外置mysql数据库操作(docker 环境)

目录 一、外置mysql数据库原因&#xff1a; 二、数据库准备工作 三、构建nacos容器 四、效果展示 一、外置mysql数据库原因&#xff1a; 想知道nacos如何外置mysql数据库之前&#xff0c;我们首先要知道为什么要外置mysql数据库&#xff0c;或者说这样做有什么优点和好处&am…

【数电】半导体存储电路

组合逻辑电路输入和输出之间是确定关系&#xff0c;与之前的历史记录没有任何关系。时序逻辑电路则有相应的存储元件&#xff0c;要把之前的状态保存起来。 要构成时序逻辑电路&#xff0c;必须要有相应的存储元件&#xff0c;第五章讲述相应的存储元件 一、半导体存储电路概…