比特数据结构与算法(第三章_上)栈的概念和实现(力扣:20. 有效的括号)
一、栈(stack)
栈的概念:
① 栈是一种特殊的线性表,它只允许在固定的一端进行插入和删除元素的操作。
② 进行数据插入的删除和操作的一端,称为栈顶 。另一端则称为 栈底 。
③ 栈中的元素遵守后进先出的原则,即 LIFO原则(Last In First Out)。
压栈:栈的插入操作叫做 进栈 / 压栈 / 入栈 ,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
两道栈的选择题:
1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E 依次入栈,
然后再依次出栈,则元素出栈的顺序是( )。
A 12345ABCDE
B EDCBA54321
C ABCDE12345
D 54321EDCBA
2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是( )。
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1
答案:
1.A
2.c
栈的结构:

数组栈和链式栈
实现栈无非就两种结构:数组结构 和 链式结构,两种结构都可以实现。
数组栈和链式栈哪种结构更好?
相对而言数组的结构实现更优,尾插尾删的效率高,缓存利用率高,它的唯一缺点只是增容,
但是增容1次扩2倍对栈来说本身就比较合理,是无伤大雅的。而链式栈虽然不会空间浪费,
用一个 malloc 申请一个,但是链式栈存在一个致命的缺点:单链表不好出数据,
必须要实现双向链表,否则尾上删除数据将会异常麻烦。
如果硬要使用链式栈:
① 如果用尾做栈顶,尾插尾删,要设计成双向链表,否则删数据效率低。
② 如果用头做栈顶,头插头删,就可以设计成单链表。
本章栈的实现将采用数组结构
二、栈的定义
(数组栈和顺序表定义差不多)
静态栈
简单介绍下静态栈:
typedef char StackDataType;
#define N 10typedef struct Stack
{
StackDataType _array[N]; //数组
int _top; //栈顶
} Stack;解读:N 给多了浪费给少了又不够用,所以静态栈在实际中是不实用的。静态栈满了就不能扩大了,
而动态栈是 malloc 出来的,不够了可以 realloc 扩容。虽然不实用,但是我们也得认识它,
知道有这么一个东西。
动态栈
本章将采用动态栈实现
typedef int StackDataType;typedef struct Stack
{StackDataType* array; //数组int top; //栈顶int capacity; //容量
} Stack;三、栈的实现(完整代码)
实现了顺序表和链表,栈的实现很简单,直接放完整代码了
Stack.h
#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int StackDataType;typedef struct Stack
{StackDataType* array; //数组int top; //栈顶int capacity; //容量
} Stack;void StackInit(Stack* ps);//初始化
void StackDestroy(Stack* ps);//销毁
void StackPush(Stack* ps, StackDataType x);//进栈
bool StackEmpty(Stack* ps);//判断栈是否为空
void StackPop(Stack* ps);// 出栈
StackDataType StackTop(Stack* ps);//返回栈顶数据
int StackSize(Stack* ps);//返回栈的大小Stack.c
#include "Stack.h"void StackInit(Stack* ps)//初始化
{assert(ps);ps->array = NULL;ps->top = 0; // ps->top = -1ps->capacity = 0;
}void StackDestroy(Stack* ps)//销毁
{assert(ps);free(ps->array);ps->array = NULL;ps->capacity = ps->top = 0;
}void StackPush(Stack* ps, StackDataType x)//进栈
{assert(ps);if (ps->top == ps->capacity) {int new_capacity = ps->capacity == 0 ? 4 : ps->capacity * 2;StackDataType* tmp_arr =(StackDataType *) realloc(ps->array, sizeof(StackDataType) * new_capacity);if (tmp_arr == NULL) {printf("realloc failed!\n");exit(-1);}// 更新ps->array = tmp_arr;ps->capacity = new_capacity;}ps->array[ps->top] = x;// 填入数据ps->top++;
}bool StackEmpty(Stack* ps)//判断栈是否为空
{assert(ps);return ps->top == 0; //等于0就是空,就是真
}void StackPop(Stack* ps)// 出栈
{assert(ps);//assert(ps->top > 0); //防止top为空assert(!StackEmpty(ps));ps->top--;
}StackDataType StackTop(Stack* ps)//返回栈顶数据
{assert(ps);//assert(ps->top > 0); //防止top为空assert(!StackEmpty(ps));return ps->array[ps->top - 1];
}int StackSize(Stack* ps) //计算栈的大小
{assert(ps);return ps->top;// 因为我们设定top是指向栈顶的下一个,所以top就是size
}Test.c
#include "Stack.h"void TestStack1()
{Stack st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPush(&st, 4);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);//StackPop(&st);printf("%d", StackTop(&st));StackDestroy(&st);
}void TestStack2()
{// 入栈:1 2 3 4Stack st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);// 出栈:4 3 2 1while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestroy(&st);
}void TestStack3()
{// 入栈:1 2 3 4Stack st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);// 提前出栈:4 3printf("%d ", StackTop(&st));StackPop(&st);printf("%d ", StackTop(&st));StackPop(&st);// 入栈:5 6StackPush(&st, 5);StackPush(&st, 6);// 出栈:6 5 2 1while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestroy(&st);
}int main()
{//TestStack1();//TestStack2();TestStack3();return 0;
}四、一道栈的OJ题:
力扣链接:20. 有效的括号
难度简单
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
提示:
1 <= s.length <= 104
s 仅由括号 '()[]{}' 组成
bool isValid(char * s){}解析代码:
这道题用C++写就很简单,用C语言写就需要创建一个栈。(可以用数组什么的,但不好)
我们刚写了一个栈,直接把Stack.h和Stack.c复制粘贴过去,把头文件删掉,
再把typedef int StackDataType; 改成typedef char StackDataType;
typedef char StackDataType;typedef struct Stack
{StackDataType* array; //数组int top; //栈顶int capacity; //容量
} Stack;void StackInit(Stack* ps);
void StackDestroy(Stack* ps);
void StackPush(Stack* ps, StackDataType x);
bool StackEmpty(Stack* ps);
void StackPop(Stack* ps);
StackDataType StackTop(Stack* ps);
int StackSize(Stack* ps);void StackInit(Stack* ps)//初始化
{assert(ps);ps->array = NULL;ps->top = 0; // ps->top = -1ps->capacity = 0;
}void StackDestroy(Stack* ps)//销毁
{assert(ps);free(ps->array);ps->array = NULL;ps->capacity = ps->top = 0;
}void StackPush(Stack* ps, StackDataType x)//进栈
{assert(ps);if (ps->top == ps->capacity) {int new_capacity = ps->capacity == 0 ? 4 : ps->capacity * 2;StackDataType* tmp_arr =(StackDataType *) realloc(ps->array, sizeof(StackDataType) * new_capacity);if (tmp_arr == NULL) {printf("realloc failed!\n");exit(-1);}// 更新ps->array = tmp_arr;ps->capacity = new_capacity;}ps->array[ps->top] = x;// 填入数据ps->top++;
}bool StackEmpty(Stack* ps)//判断栈是否为空
{assert(ps);return ps->top == 0; //等于0就是空,就是真
}void StackPop(Stack* ps)// 出栈
{assert(ps);//assert(ps->top > 0); //防止top为空assert(!StackEmpty(ps));ps->top--;
}StackDataType StackTop(Stack* ps)//返回栈顶数据
{assert(ps);//assert(ps->top > 0); //防止top为空assert(!StackEmpty(ps));return ps->array[ps->top - 1];
}int StackSize(Stack* ps) //计算栈的大小
{assert(ps);return ps->top;// 因为我们设定top是指向栈顶的下一个,所以top就是size
}bool isValid(char* s) {Stack st;StackInit(&st);while (*s){if ((*s == '(') || (*s == '[') || (*s == '{')){StackPush(&st, *s);}else{//栈是空,且遇到右括号了,栈里面没有左括号if (StackEmpty(&st)){StackDestroy(&st);return false;}StackDataType top = StackTop(&st);StackPop(&st);if ((top == '(' && *s != ')')|| (top == '[' && *s != ']')|| (top == '{' && *s != '}')){StackDestroy(&st);return false;}}s++;}//如果栈不是空,说明还有左括号没出完,不合题意//此时StackEmpty返回false,相反,栈是空,返回truebool ret = StackEmpty(&st);StackDestroy(&st);return ret;
}本篇完,下一篇:队列
相关文章:
比特数据结构与算法(第三章_上)栈的概念和实现(力扣:20. 有效的括号)
一、栈(stack)栈的概念:① 栈是一种特殊的线性表,它只允许在固定的一端进行插入和删除元素的操作。② 进行数据插入的删除和操作的一端,称为栈顶 。另一端则称为 栈底 。③ 栈中的元素遵守后进先出的原则,即…...
JVM13 类的生命周期
1. 概述 在 Java 中数据类型分为基本数据类型和引用数据类型。基本数据类型由虚拟机预先定义,引用数据类型则需要进行类的加载。 按照 Java 虚拟机规范,从 class 文件到加载到内存中的类,到类卸载出内存为止,它的整个生命周期包…...
Docker网络模式解析
目录 前言 一、常用基本命令 (一)查看网络 (二)创建网络 (三)查看网络源数据 (四)删除网络 二、网络模式 (一)总体介绍 (二)…...
游山城重庆
山城楼梯多,路都是上坡。 为了赶早上8点从成都到重庆的动车,凌晨5点半就爬起床来,由于昨天喝了咖啡,所以我将尽3点才睡觉,这意味着我只睡了2个多小时。起来简单休息之后,和朋友协商好时间就一起出门了。 …...
Vuex的创建和简单使用
Vuex 1.简介 1.1简介 1.框框里面才是Vuex state:状态数据action:处理异步mutations:处理同步,视图可以同步进行渲染1.2项目创建 1.vue create 名称 2.运行后 3.下载vuex。采用的是基于vue2的版本。 npm install vuex3 --save 4.vu…...
Arduino IDE搭建Heltec开发板开发环境
Arduino IDE搭建Heltec开发板开发环境Heltec开发板开发环境下载与搭建Arduino IDE下载与安装搭建Heltec开发板的开发环境添加package URL方法通过Git的方法安装离线安装Heltec开发板开发环境下载与搭建 Arduino IDE下载与安装 Heltec的ESP系列和大部分的LoRa系列开发板都是用A…...
Using the GNU Compiler Collection 目录翻译
文章目录Introduction1 Programming Languages Supported by GCC2 Language Standards Supported by GCC2.1 C Language3 GCC Command Options3.1 Option Summary4 C Implementation-Defined Behavior6 Extensions to the C Language Family9 Binary Compatibility其他工具10 g…...
使用 OpenCV for Android 进行图像特征检测
android 开发人员,可能熟悉使用activities, fragments, intents以及最重要的一系列开源依赖库。但是,注入需要本机功能的依赖关系(如计算机视觉框架)并不像在 gradle 文件中直接添加实现语句那样简单!今天,将专注于使用 OpenCV 库…...
chatGPT笔记
文章目录 一、GPT之技术演进时间线二、chatGPT中的语言模型instructGPT跟传统语言LM模型最大不同点是什么?三、instructGPT跟GPT-3的网络结构是否一样四、GPT和BERT有啥区别五、chatGPT的训练过程是怎样的?六、GPT3在算数方面的能力七、GPT相比于bert的优点是什么八、元学习(…...
这么好的政策和创新基地,年轻人有梦想你就来
周末有空去参观了下一个朋友办的公司。位置和环境真不错,且租金低的离谱,半年租金才2000元,且提供4个工位。这个创新基地真不赖啊,国家鼓励创新创业,助力年轻人实现梦想。场地有办公区,休息区应有尽有&…...
【Kubernetes】【十九】安全认证
第九章 安全认证 本章节主要介绍Kubernetes的安全认证机制。 访问控制概述 Kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。 客户端 在Kubernetes集群…...
Apache Flink 实时计算在美的多业务场景下的应用与实践
摘要:本文整理自美的集团实时数据负责人、资深数据架构师董奇,在 Flink Forward Asia 2022 主会场的分享。本篇内容主要分为四个部分: 实时生态系统在美的的发展和建设现状 核心传统业务场景 Flink 实时数字化转型实践 新兴业务场景 Flink …...
27 pandas 数据透视
文章目录pivot_table 函数1、index需要聚合的列名,默认情况下聚合所有数据值的列2、values在结果透视的行上进行分组的列名或其它分组键【就是透视表里显示的列】3、columns在结果透视表的列上进行分组的列名或其它分组键4、Aggfunc聚合函数或函数列表(默…...
1.2 学习环境准备
文章目录1.MariaDB简介2.MariaDB服务端和客户端安装1.MariaDB简介 因为MariaDB作为MySQL的延申,其包含MySQL所有的有点,并且其包含了更丰富的特性。比如微秒的支持、线程池、子查询优化、组提交、进度报告等; 所以我们接下来将已MariaDB作为…...
Http1.0协议常识
组织:中国互动出版网(http://www.china-pub.com/)RFC文档中文翻译计划(http://www.china-pub.com/compters/emook/aboutemook.htm)E-mail:ouyangchina-pub.com译者:黄晓东(黄晓东 xd…...
“终于懂了” 系列:组件化框架 ARouter 完全解析(三)AGP/Transform/ASM—动态代码注入
ARouter系列文章: “终于懂了” 系列:组件化框架 ARouter 完全解析(一)原理全解 “终于懂了” 系列:组件化框架 ARouter 完全解析(二)APT—帮助类生成 “终于懂了” 系列:组件化框架…...
传闻腾讯引进Quest 2?我觉得可行性很低
根据36kr最新消息称,腾讯XR团队解散后,确定不碰XR硬件领域,但并未完全放弃XR规划,将转变思路和玩法,业内消息称腾讯计划引进Meta旗下Quest 2 VR一体机。消息称,该计划在2022年11月份XR部门负责人沈黎走后便…...
【数据集】CMIP6气候模式数据下载
1 CMIP6简介 目前,国际耦合模式比较计划(Coupled Model Intercomparison Project, CMIP) 已经发展到第六阶段(CMIP6)。CMIP6模式采用了较以往更加合理的参数化方案,综合考虑了大气中温室气体排放、气溶胶浓度及社会经济、科学技术发展及政府规划等多方面的综合影响,将提…...
华为OD机试 - 最长的元音字符串 | 机试题算法思路 【2023】
最近更新的博客 华为OD机试 - 简易压缩算法(Python) | 机试题算法思路 【2023】 华为OD机试题 - 获取最大软件版本号(JavaScript) 华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】 华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】 华为OD机试 …...
浅谈c++引用
浅谈c 在这里开设 <<浅谈C>> 系列专题,针对C重点内容展开探讨与观察底层,同时也是一个面试专栏,所选知识大多为面试常见问题.前期较为基础,难度会逐渐上升哦~ 本专栏采用经典的哲学三段论编写:是什么|为什么|怎么做 力图精简,高效. 第一章: 浅谈C函数重载 传送门…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
