当前位置: 首页 > news >正文

比特数据结构与算法(第三章_上)栈的概念和实现(力扣: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. 左括号必须用相同类型的右括号闭合。

  1. 左括号必须以正确的顺序闭合。

  1. 每个右括号都有一个对应的相同类型的左括号。

示例 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. 有效的括号)

一、栈&#xff08;stack&#xff09;栈的概念&#xff1a;① 栈是一种特殊的线性表&#xff0c;它只允许在固定的一端进行插入和删除元素的操作。② 进行数据插入的删除和操作的一端&#xff0c;称为栈顶 。另一端则称为 栈底 。③ 栈中的元素遵守后进先出的原则&#xff0c;即…...

JVM13 类的生命周期

1. 概述 在 Java 中数据类型分为基本数据类型和引用数据类型。基本数据类型由虚拟机预先定义&#xff0c;引用数据类型则需要进行类的加载。 按照 Java 虚拟机规范&#xff0c;从 class 文件到加载到内存中的类&#xff0c;到类卸载出内存为止&#xff0c;它的整个生命周期包…...

Docker网络模式解析

目录 前言 一、常用基本命令 &#xff08;一&#xff09;查看网络 &#xff08;二&#xff09;创建网络 &#xff08;三&#xff09;查看网络源数据 &#xff08;四&#xff09;删除网络 二、网络模式 &#xff08;一&#xff09;总体介绍 &#xff08;二&#xff09…...

游山城重庆

山城楼梯多&#xff0c;路都是上坡。 为了赶早上8点从成都到重庆的动车&#xff0c;凌晨5点半就爬起床来&#xff0c;由于昨天喝了咖啡&#xff0c;所以我将尽3点才睡觉&#xff0c;这意味着我只睡了2个多小时。起来简单休息之后&#xff0c;和朋友协商好时间就一起出门了。 …...

Vuex的创建和简单使用

Vuex 1.简介 1.1简介 1.框框里面才是Vuex state&#xff1a;状态数据action&#xff1a;处理异步mutations&#xff1a;处理同步&#xff0c;视图可以同步进行渲染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 开发人员&#xff0c;可能熟悉使用activities, fragments, intents以及最重要的一系列开源依赖库。但是&#xff0c;注入需要本机功能的依赖关系(如计算机视觉框架)并不像在 gradle 文件中直接添加实现语句那样简单&#xff01;今天&#xff0c;将专注于使用 OpenCV 库…...

chatGPT笔记

文章目录 一、GPT之技术演进时间线二、chatGPT中的语言模型instructGPT跟传统语言LM模型最大不同点是什么?三、instructGPT跟GPT-3的网络结构是否一样四、GPT和BERT有啥区别五、chatGPT的训练过程是怎样的?六、GPT3在算数方面的能力七、GPT相比于bert的优点是什么八、元学习(…...

这么好的政策和创新基地,年轻人有梦想你就来

周末有空去参观了下一个朋友办的公司。位置和环境真不错&#xff0c;且租金低的离谱&#xff0c;半年租金才2000元&#xff0c;且提供4个工位。这个创新基地真不赖啊&#xff0c;国家鼓励创新创业&#xff0c;助力年轻人实现梦想。场地有办公区&#xff0c;休息区应有尽有&…...

【Kubernetes】【十九】安全认证

第九章 安全认证 本章节主要介绍Kubernetes的安全认证机制。 访问控制概述 ​ Kubernetes作为一个分布式集群的管理工具&#xff0c;保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。 客户端 在Kubernetes集群…...

Apache Flink 实时计算在美的多业务场景下的应用与实践

摘要&#xff1a;本文整理自美的集团实时数据负责人、资深数据架构师董奇&#xff0c;在 Flink Forward Asia 2022 主会场的分享。本篇内容主要分为四个部分&#xff1a; 实时生态系统在美的的发展和建设现状 核心传统业务场景 Flink 实时数字化转型实践 新兴业务场景 Flink …...

27 pandas 数据透视

文章目录pivot_table 函数1、index需要聚合的列名&#xff0c;默认情况下聚合所有数据值的列2、values在结果透视的行上进行分组的列名或其它分组键【就是透视表里显示的列】3、columns在结果透视表的列上进行分组的列名或其它分组键4、Aggfunc聚合函数或函数列表&#xff08;默…...

1.2 学习环境准备

文章目录1.MariaDB简介2.MariaDB服务端和客户端安装1.MariaDB简介 因为MariaDB作为MySQL的延申&#xff0c;其包含MySQL所有的有点&#xff0c;并且其包含了更丰富的特性。比如微秒的支持、线程池、子查询优化、组提交、进度报告等&#xff1b; 所以我们接下来将已MariaDB作为…...

Http1.0协议常识

组织&#xff1a;中国互动出版网&#xff08;http://www.china-pub.com/&#xff09;RFC文档中文翻译计划&#xff08;http://www.china-pub.com/compters/emook/aboutemook.htm&#xff09;E-mail&#xff1a;ouyangchina-pub.com译者&#xff1a;黄晓东&#xff08;黄晓东 xd…...

“终于懂了” 系列:组件化框架 ARouter 完全解析(三)AGP/Transform/ASM—动态代码注入

ARouter系列文章&#xff1a; “终于懂了” 系列&#xff1a;组件化框架 ARouter 完全解析&#xff08;一&#xff09;原理全解 “终于懂了” 系列&#xff1a;组件化框架 ARouter 完全解析&#xff08;二&#xff09;APT—帮助类生成 “终于懂了” 系列&#xff1a;组件化框架…...

传闻腾讯引进Quest 2?我觉得可行性很低

根据36kr最新消息称&#xff0c;腾讯XR团队解散后&#xff0c;确定不碰XR硬件领域&#xff0c;但并未完全放弃XR规划&#xff0c;将转变思路和玩法&#xff0c;业内消息称腾讯计划引进Meta旗下Quest 2 VR一体机。消息称&#xff0c;该计划在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函数重载 传送门…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...