栈的实现与OJ括号匹配

今日备忘录: "不破不立. "

本文索引

  • 1. 前言
  • 2. 顺序表与链表的区别
  • 3. 什么是栈
  • 4. 栈的实现
  • 5. OJ括号匹配
  • 6. 总结

1. 前言

人总是在坍塌中重建, 有些东西必须摧毁, 才能迎来新生, 不管是那些消耗你的人, 还是令你感到焦虑的事情, 还是一份你觉得毫无意义并且又不喜欢的工作, 又或者是那个内心敏感的自己, 总之你害怕什么, 就要去面对什么, 你想要什么, 就要去靠近什么, 在声色名利中守住本性, 在世俗目光中信步前行, 大浪淘沙, 去伪存真, 破而后立, 否极泰来.

本文旨在探讨数据结构中栈的实现以及顺序表与链表区别总结.
更多精彩, 期待关注 主页: 酷酷学!!!

2. 顺序表与链表的区别

在实现栈之前, 我们先总结一下顺序表和链表
在这里插入图片描述
以上是顺序表与链表比较全面的区别总结, 在插入数据时链表没有容量的概念指的是链表的空间是使用多少开辟多少, 不会进行扩容操作, 也不会造成容量的浪费.

那么什么是缓存利用率,简单讲解一下

在这里插入图片描述
以上是存储器的结构层次,由于CPU的访问速度非常的快, 它不会直接访问内存, 因为内存的读写速度太慢了, 而是将数据先逐层转移到寄存器或者高速缓存中,在进行读写, 一般寄存器存放字节大小为8的数据, 然后CPU再进行访问, 但是如何将数据转移到缓存当中的呢, 为什么说顺序表缓存利用率高而链表低呢?

在这里插入图片描述

在将内存中的数据运送到缓存中的时候, 不是一个一个传输的,而是将连带后面的一块空间直接一起运送到缓存中, 如同一辆大巴车一样, 不是一个一个运送, 而是包括后面的一块空间一起运输, 然后CPU在从缓存中进行读写, 那么, 如果继续往后读写, 在缓存中, 我们称之为缓存命中, 直接访问, 如果不在缓存中, 我们称之为不命中, 要把数据从内存加载到缓存中, 在进行访问, 如此看来所以 顺序表的缓存利用率肯定高于链表

更多资讯, 可以点击参考 与程序员相关的CPU缓存知识

3. 什么是栈

: 一种特殊的线性表, 其只允许在固定的一端进行插入和删除元素操作. 在进行数据插入和删除操作的一端称之为栈顶, 另一端称之为栈底. 栈中的元素遵守后进先出LIFO(Last In First Out)原则.

压栈 : 栈的插入操作叫做压栈或入栈, 入数据在栈顶
出栈 : 栈的删除操作叫做出栈. 出数据也在栈顶.

在这里插入图片描述
在这里插入图片描述

4. 栈的实现

栈的实现一般可以使用数组或者链表进行实现, 相对而言数组的结构实现更优一些, 因为在数组上尾插数据的代价比较小, 而且数组的缓存利用率比较高.

在这里插入图片描述
在这里插入图片描述
第一步:

创建三个文件
在这里插入图片描述
在头文件中进行结构定义和函数声明

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int STDatatype;
typedef struct Stack
{STDatatype* a;int top;int capacity;
}ST;//初始化
void InitStack(ST* pst);
//销毁
void Destory(ST* pst);//压栈
void Push(ST* pst,STDatatype x);
//出栈
void Pop(ST* pst);
//取栈顶元素
STDatatype STTop(ST* pst);//判空
bool Empty(ST* pst);
//获取元素个数
int Size(ST* pst);

第二步:
实现栈的方法

  • 初始化
void InitStack(ST* pst)
{assert(pst);pst->a = NULL;pst->capacity = pst->top = 0;
}

注意
top的值根据自己的情况定义, 若top=0,表示指向栈顶数据下一个位置, top=-1,表示指向栈顶数据.
在这里插入图片描述

首先断言,这里肯定不能给我传一个NULL, 然后进行常规操作

  • 销毁
void Destory(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}

动态顺序表, 空间需要手动释放

  • 压栈
void Push(ST* pst, STDatatype x)
{assert(pst);if (pst->capacity == pst->top){int Newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;STDatatype* tmp = (STDatatype*)realloc(pst->a,sizeof(STDatatype) * Newcapacity);if (tmp == NULL){perror("malloc fail");return;}pst->a = tmp;pst->capacity = Newcapacity;}pst->a[pst->top] = x;pst->top++;
}

因为我们初始化的时候没有开辟空间, 所以如果栈为空的时候, 我们先开辟四个空间, 当栈满时, 我们在成倍扩容, 然后先用临时变量存储首地址, 防止申请失败原地址丢失, 然后更改空间容量大小, 最后在进行写入数据.

  • 销毁
void Pop(ST* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}

首先栈不能为NULL, 并且需要有数据, 然后直接top-- 就行.

  • 获取栈顶元素
STDatatype STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top-1];
}

直接返回top的前一个位置

  • 判断栈是否为空
bool Empty(ST* pst)
{assert(pst);return pst->top == 0;
}

如果top为0则栈为空

  • 获取数据个数
int Size(ST* pst)
{assert(pst);return pst->top;
}

top表示下标, 也就是元素个数

5. OJ括号匹配

题目链接: 有效的括号

题目描述:

在这里插入图片描述
题目分析:

首先题目有三个要求

  1. 左括号必须用相同类型的右括号进行闭合.
  2. 左括号必须以正确的顺序闭合
  3. 每个左括号都有一个对应相同类型的左括号

如果我们直接用左括号个数与右括号进行比较的话, 那么顺序问题我们无法解决, 而栈这种后进先出的结构恰好可以解决这种问题, 当遇到左括号时进行压栈, 遇到右括号时将左括号出栈, 进行比较, 正好解决了顺序问题, 但是C语言没有栈这种结构, 所以我们需要自己写栈这种结构.
于是我们很容易写出下面的代码.

bool isValid(char* s) {ST stack;InitStack(&stack);while (*s){//左括号压栈if (*s == '(' || *s == '{' || *s == '['){Push(&stack, *s);s++;}//右括号与栈顶左括号进行匹配else{char tmp = STTop(&stack);Pop(&stack);//如果不匹配if ((tmp == '(' && *s != ')')|| (tmp == '[' && *s != ']')|| (tmp == "{" && *s != '}')){return false;Destory(&stack);}}}return true;Destory(&stack);
}

但是这样写真的对吗, 答案是错的, 因为如果只有左括号的情况, 和只有右括号的情况, 我们还需要加以判断. 修正代码
字符串只有右括号, 先判断栈是否为空, 若为空返回false,并且释放栈

字符串只有左括号, 循环结束, 看看栈中元素还有没有, 如果还有则返回false,并且销毁栈

bool isValid(char* s) {ST stack;InitStack(&stack);while (*s) {// 左括号压栈if (*s == '(' || *s == '{' || *s == '[') {Push(&stack, *s);}// 右括号与栈顶左括号进行匹配else {if (Empty(&stack)) {Destory(&stack);return false;}char tmp = STTop(&stack);Pop(&stack);// 如果不匹配if ((tmp == '(' && *s != ')') || (tmp == '[' && *s != ']') ||(tmp == '{' && *s != '}')) {Destory(&stack);return false;}}++s;}bool ret = Empty(&stack);Destory(&stack);return ret;
}

全部代码如下:

typedef char STDatatype;
typedef struct Stack {STDatatype* a;int top;int capacity;
} ST;// 初始化
void InitStack(ST* pst);
// 销毁
void Destory(ST* pst);// 压栈
void Push(ST* pst, STDatatype x);
// 出栈
void Pop(ST* pst);
// 取栈顶元素
STDatatype STTop(ST* pst);// 判空
bool Empty(ST* pst);
// 获取元素个数
int Size(ST* pst);void InitStack(ST* pst) {assert(pst);pst->a = NULL;pst->capacity = pst->top = 0;
}void Destory(ST* pst) {assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}void Push(ST* pst, STDatatype x) {assert(pst);if (pst->capacity == pst->top) {int Newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;STDatatype* tmp =(STDatatype*)realloc(pst->a, sizeof(STDatatype) * Newcapacity);if (tmp == NULL) {perror("malloc fail");return;}pst->a = tmp;pst->capacity = Newcapacity;}pst->a[pst->top] = x;pst->top++;
}void Pop(ST* pst) {assert(pst);assert(pst->top > 0);pst->top--;
}STDatatype STTop(ST* pst) {assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];
}bool Empty(ST* pst) {assert(pst);return pst->top == 0;
}int Size(ST* pst) {assert(pst);return pst->top;
}bool isValid(char* s) {ST stack;InitStack(&stack);while (*s) {// 左括号压栈if (*s == '(' || *s == '{' || *s == '[') {Push(&stack, *s);}// 右括号与栈顶左括号进行匹配else {if (Empty(&stack)) {Destory(&stack);return false;}char tmp = STTop(&stack);Pop(&stack);// 如果不匹配if ((tmp == '(' && *s != ')') || (tmp == '[' && *s != ']') ||(tmp == '{' && *s != '}')) {Destory(&stack);return false;}}++s;}bool ret = Empty(&stack);Destory(&stack);return ret;
}

6. 总结

栈是一种线性数据结构,具有后进先出(LIFO)的特点,即最后进入栈的元素最先被访问或删除。栈通常有两种基本操作:压栈(push)和弹栈(pop),分别用于将元素压入栈顶和从栈顶弹出元素。

栈的应用非常广泛,常见的应用包括表达式求值、函数调用、浏览器的前进后退功能等。在计算机科学中,栈也被用于实现递归算法、解决括号匹配等问题。

栈的实现方式有多种,包括基于数组和基于链表的实现。基于数组的实现通常需要指定栈的最大容量,而基于链表的实现则可以动态调整大小。

总的来说,栈是一种非常重要且常用的数据结构,掌握栈的基本操作和应用场景对于理解算法和数据结构有着重要的意义。

如果此文有帮助 感谢点赞关注!!!

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

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

相关文章

python词云图形状修改

python词云图形状修改 词云图介绍wordcloud介绍修改形状参数效果代码 词云图介绍 词云图&#xff08;Word Cloud&#xff09;是一种文本数据的可视化表示形式&#xff0c;它通过字体大小、颜色、布局等视觉元素来展示文本中不同词汇的频率或重要性。词云图中&#xff0c;出现频…

南京中科微Ci24R1(DFN8)无线收发射频芯片性能介绍

Ci24R1是南京中科微研发的低成本高性能2.4GHz GFSK 无线收发芯片&#xff08;支持蓝牙版&#xff09;&#xff0c;专为低功耗无限场合设计&#xff0c;集成嵌入式ARQ基带协议引擎的无线收发器芯片。 工作频率为2400MHz-2525MHz&#xff0c;共有126个1MHz带宽的信道&#xff0c…

.NET 复现某多媒体中间件文件上传漏洞

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

如何挑选“好用”的工业APP

我们日常生活中每天都在使用各种生活类的APP,然而&#xff0c;当我们谈到工业APP时&#xff0c;很多人可能并不那么熟悉。工业APP&#xff0c;虽然不像生活类APP那样直接面向广大消费者&#xff0c;但在工业领域却扮演着至关重要的角色。 先简单认识下啥是工业APP? 工业APP是…

“交个朋友”申请注册商标都已被驳回!

“ 交个朋友”在直播带货界非常有名&#xff0c;普推知产老杨在商标局官网上检索发现&#xff0c;“交个朋友”主体申请了以“交个朋友”四百多个相关商标&#xff0c;基本上都被驳回&#xff0c;其实这样的名称不应提报商标&#xff0c;专业商标人员一看就过不了&#xff0c;还…

水经微图万能版、专业版与企业版的区别?

水经微图&#xff08;以下简称“微图”&#xff09;的版本&#xff0c;主要分为万能版、专业版和企业版三个版本。 什么是万能版&#xff1f; 万能版是指“水经注万能地图下载器”软件功能的授权&#xff0c;虽然该软件已经停止更新&#xff0c;但购买过该软件的用户&#xf…

成都数字产业园深度链接校企双方,共建产学研合作研发中心

在数字经济的浪潮中&#xff0c;企业与学院之间的深度链接显得尤为关键。作为人才输送的源头&#xff0c;学院承载着为社会培育高素质人才的使命&#xff1b;而作为创新与实践的基地&#xff0c;企业则渴望吸引这些新鲜血液&#xff0c;为自身的持续发展注入新的活力。近日&…

MQTT学习(一)

MQTT是一种与HTTP类似的应用层协议。 在某些物联网应用中&#xff0c;MQTT优于HTTP。 首先&#xff0c;HTTP是用于客户端服务器计算的以文档为中心的请求-响应协议。 HTTP是万维网的基础&#xff0c;但它不是专门为机器之间通信而设计的。 MQTT是一种机器对机器、以数据为中…

netty配置SSL、netty配置https(生产环境)

netty配置SSL、netty配置https&#xff08;生产环境&#xff09; 上一篇提到了如何在开发环境使用SSL&#xff1a;https://lingkang.top/archives/netty-pei-zhi-ssl 转自&#xff1a;https://lingkang.top/archives/netty-pei-zhi-https 那么netty如何使用可信任的证书呢&a…

运筹系列92:vrp算法包VROOM

1. 介绍 VROOM is an open-source optimization engine written in C20 that aim at providing good solutions to various real-life vehicle routing problems (VRP) within a small computing time. 可以解决如下问题&#xff1a; TSP (travelling salesman problem) CVRP …

Linux提权--SUDO(CVE-2021-3156)Polkit(CVE-2021-4034)

免责声明:本文仅做技术学习与交流... 目录 SUDO(CVE-2021-3156) 影响版本 -判断&#xff1a; -利用&#xff1a; Polkit(CVE-2021-4034&#xff09; ​ -判断&#xff1a; -利用: 添加用户 SUDO(CVE-2021-3156) another: SUDO权限配置不当. 影响版本 由系统的内核和发…

MODIFY DUMP

写了一个modify的语句&#xff0c;但是dump了 查阅资料 参考一下链接 ABAP 内表修改 MODIFY 和 MODIFY table 的区别-CSDN博客

品鉴中的风味轮:如何运用专业工具解读红酒的复杂风味

品鉴云仓酒庄雷盛红酒时&#xff0c;我们常常会遇到各种各样复杂的味道。为了更好地理解和描述这些风味&#xff0c;专业工具——风味轮被引入到红酒品鉴中。通过运用风味轮&#xff0c;我们可以更科学、更具体地解读红酒的复杂风味。 风味轮是一种包含一系列风味和味道描述的圆…

PCIE协议-2-事务层规范-Message Request Rules-Vendor_Defined Messages

2.2.8.6 厂商定义消息 厂商定义消息允许扩展PCI Express消息功能&#xff0c;可以作为PCI Express规范的一般扩展&#xff0c;也可以是厂商特定的扩展。本节通用地定义了与这些消息相关的规则。 厂商定义消息&#xff08;见表2-25&#xff09;使用图2-28中显示的头标格式。re…

【车企招聘】Android车载开发全套学习资料(收藏版)

前言 随着人工智能技术的迅速发展&#xff0c;智能车机系统已成为汽车行业的热门趋势&#xff0c;旨在提升驾乘人员的体验和安全性。在中高端车型中广泛应用智能车机系统&#xff0c;其中包含了语音识别控制、人脸识别、手势识别、智能紧急刹车等功能&#xff0c;为驾驶者提供…

常用的内外网文件传输方式及优缺点

在现代企业环境中&#xff0c;内外网文件传输是一项至关重要的任务。这涉及到数据的安全性、传输效率以及操作的便捷性等多个方面。 每种方式都有其独特的优缺点&#xff0c;下面我们将逐一进行分析。 1、FileLink 优势&#xff1a;FileLink是一款专用于企业内外网隔离后的文…

MySQL从入门到高级 --- 6.函数

文章目录 第六章&#xff1a;6.函数6.1 聚合函数6.2 数学函数6.3 字符串函数6.4 日期函数6.4.1 日期格式 6.5 控制流函数6.5.1 if逻辑判断语句6.5.2 case when语句 6.6 窗口函数6.6.1 序号函数6.6.2 开窗聚合函数6.6.3 分布函数6.6.4 前后函数6.6.5 头尾函数6.6.6 其他函数6.7 …

申贷时,银行级大数据自己能查到吗?

随着金融风控的不断健全&#xff0c;大数据作为辅助的风控工具正在被越来越多的银行和机构使用。在进行申贷时&#xff0c;银行通常会进行大数据查询&#xff0c;以便评估申请人的信用状况。那么&#xff0c;这些大数据自己能查到吗?接下来本文就为大家详细介绍一下&#xff0…

怎样才能不当数据泄露的下一个受害者?

在数字化时代&#xff0c;数据泄露成为了所有企业必须面对的难题。无论规模大小&#xff0c;每家公司都可能成为黑客攻击的目标&#xff0c;从而遭受数据泄露的风险。然而&#xff0c;通过采取一系列预防措施&#xff0c;企业可以极大地降低成为下一个受害者的可能性。 教育员…

哪些AI软件可以帮助我快速制作PPT?推荐几个aippt工具

提起PPT&#xff0c;大家的第一反应就是痛苦。经常接触PPT的学生党和打工人&#xff0c;光看到这3个字母&#xff0c;就已经开始头痛了&#xff1a; 1、PPT内容框架与文案挑战重重&#xff0c;任务艰巨&#xff0c;耗费大量精力。 2、PPT的排版技能要求高&#xff0c;并非易事…