数据结构—栈(C语言实现)
文章目录
- 前言
- 一、栈的概念
- 二、栈的代码实现
- Stack.h
- Stack.c
- 三、使用栈解决有效的括号问题
- 总结
前言
小伙伴们,大家好哇!!欢迎来到我的博客!
今天来分享一下另外一种数据结构—栈。主要包括栈的基本概念与其代码实现,最后使用该数据结构巧妙地解决一道算法题。
一、栈的概念
栈(stack)是一种特殊的线性表,它只允许从一段插入删除数据,进行插入删除操作的一端称为栈顶,另一端则称之为栈底。所以栈中的数据始终遵从先进后出 LINO(Last In First Out)的原则。
看到这小伙伴们可能会联想到一些日常生活中的例子,比如一包抽纸,我们每次抽出的纸肯定是最顶部一张,逐渐往下抽,直到抽到底,这里的顶部便相当于栈顶,而底部则相当于栈底。而且在纸巾实际放入包装袋中也是从底部开始放进去的。
又比如一个装了东西的箱子,我们要取出其中的物品,肯定是要从最上面的东西开始拿出(当然也不排除有些人将箱子里的东西全部暴力地倒出),直到找到自己要找的。
而像前面的插入数据的操作就叫压栈,也可以叫入栈或进栈,删除数据的操作则是出栈,在栈中插入与删除数据的位置都是栈顶。
二、栈的代码实现
讲完了栈的基本概念与思想,那么就又到了紧张刺激手撕代码的时间了。
但在实现栈之前,我们应思考一下应使用数组还是链表实现:
其实,栈一般既可以使用数组也可以使用链表实现。但相对而言,使用数组结构实现更优。因为数组在尾部插入数据的代价更小。
那么接下来就让我们使用数组来手搓一个栈吧!!
Stack.h
首先是栈的结构体声明,与之前的顺序表【数据结构—顺序表(C语言实现)】类似的是,我们当然可以使用静态栈的结构,即在声明是确定数组的长度,但这种栈在实际中并不实用:
typedef int STDataType;
#define N 10
typedef struct Stack
{STDataType _a[N];int _top; // 栈顶
}Stack;
所以我们依然是要实现可以支持动态增长的栈:
typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
然后是头文件包含与栈的结构体声明(top指向栈顶元素):
#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
最后是栈的基本方法的声明:
//初始化、销毁栈
void STInit(ST* pst);
void STDestroy(ST* pst);
//入栈、出栈
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
//判空
bool STEmpty(ST* pst);
//获取栈顶元素
STDataType STTop(ST* pst);
//获取栈有效元素个数
int STSize(ST* pst);
Stack.c
接下来就是栈的增删查改的基本方法的实现了!
首先最为基本的当然是栈的头文件包含了:
#include "Stack.h"
然后是栈的初始化与销毁:
void STInit(ST* pst)
{assert(pst);pst->a = NULL;pst->top = 0;pst->capacity = 0;
}void STDestroy(ST* pst)
{assert(pst && pst->capacity);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}
入栈,这里我们使用与之前顺序表相同的方法对栈进行扩容:
void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}pst->a = tmp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}
使用动画解释入栈操作:
出栈,这就非常简单了!只需要将栈的size–即可:
void STPop(ST* pst)
{assert(pst && pst->top);pst->top--;
}
动画解释出栈操作(由于只是将size–,实际上栈中的数据并没有消失):
最后就是栈的判空,获取栈顶数据,获取栈的数据大小(这里就很简单了,基本一行代码即可解决):
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}STDataType STTop(ST* pst)
{assert(pst && pst->top);return pst->a[pst->top - 1];
}int STSize(ST* pst)
{assert(pst);return pst->top;
}
三、使用栈解决有效的括号问题
讲完了栈的数据结构,接下来我们就可以使用栈的特性来巧妙地解决一道力扣上的算法题,附上题目链接:有效的括号。
由题意可知与我们日常学习可知:只有最近的两括号是同种(比如都是花括号:{}),并且前一个是左括号而后一个是右括号才能称之为有效的括号。
此时就是栈这一数据结构的回合了:我们可以先判断第一个字符是否为左括号,是就直接让该括号入栈;然后判断下一个字符,是左括号就入栈,不是则说明是右括号,这时就需要判断这个右括号与栈顶的括号是否匹配,匹配就让栈顶出栈,否则就直接返回false。但在判断第一个字符时是可能就为右括号的,此时我们就需要在判断括号是否匹配之前对栈进行判空操作,并返回false。而这些出栈与入栈的操作肯定是需要放到一个循环中的。
然后在出了循环我们就只需要判断此时栈中是否为空即可,为空就说明所有的括号都匹配。
接下来就是关于这道题的代码实现了。由于我们使用的是C语言解决,我们肯定需要在首先主逻辑之前手搓一个栈。但是如果我们已经在编译器中实现了一个栈,那我们就可以直接使用CV大法,10秒内完成!!(当然没有实现过栈的小伙伴最好在做这题前手撕一个栈,有助于对栈的理解)
以下是题中的主要逻辑部分的代码(当然在这之前肯定得包含栈的实现代码):
bool isValid(char* s) {ST st;STInit(&st);while (*s){if (*s == '(' || *s == '[' || *s == '{') STPush(&st, *s);else{if (STEmpty(&st)){STDestroy(&st);return false;}if (STTop(&st) == '(' && *s != ')' ||STTop(&st) == '[' && *s != ']' ||STTop(&st) == '{' && *s != '}'){STDestroy(&st);return false;}STPop(&st);}s++;}bool ret = STEmpty(&st);STDestroy(&st);return ret;
}
总结
以上就是有关栈这一数据结构的问题分享,如果觉得对你有帮助的话,希望小伙伴们可以点点“栈”(赞)!!
☆*: .。. o(≧▽≦)o .。.:*☆
相关文章:

数据结构—栈(C语言实现)
文章目录 前言一、栈的概念二、栈的代码实现Stack.hStack.c 三、使用栈解决有效的括号问题总结 前言 小伙伴们,大家好哇!!欢迎来到我的博客! 今天来分享一下另外一种数据结构—栈。主要包括栈的基本概念与其代码实现,…...

JVM学习-垃圾回收器(一)
垃圾回收器 按线程数分类 串行垃圾回收器 串行回收是在同一时间段内只允许有一个CPU用于执行垃圾回收操作,此时工作线程被暂停,直至垃圾收集工作结束 在诸如单CPU处理器或者较小的应用内存等硬件平台不是特别优越的场合,串行回收器的性能表…...

dolphinscheduler standalone安装
官方文档:https://dolphinscheduler.apache.org/en-us/docs/3.1.3/guide/installation/standalone 1.安装(以放在/home为例) 下载见:https://download.csdn.net/download/taotao_guiwang/89311365 tar -xvzf apache-dolphinsche…...
力扣hot 100:49. 字母异位词分组(python C++)
目录 题目描述:题解(python):(方法一:排序)代码解析代码运行解析 题解(C):(方法一:排序)代码解析&运行解析 原题目链接…...

男士内裤什么材质的好?推荐男士内裤的注意事项
天气已经逐渐热了起来,广大男士们在夏天难免会出一身的汗,不少男士朋友都觉得一些吸湿性、透气性不好的内裤会在夏天穿着很不适,想挑选一些比较适合夏天的男士内裤,但现在的男士内裤品牌和材质分类却比较多,看得大家眼…...

Python操作MySQL数据库的工具--sqlalchemy
文章目录 一、pymysql和sqlalchemy的区别二、sqlalchemy的详细使用1.安装库2.核心思想3.整体思路4.sqlalchemy需要连接数据库5.使用步骤1.手动提前创建数据库2.使用代码创建数据表3.用代码操作数据表3.1 增加数据3.2 查询数据3.3 删除数据3.4 修改数据 一、pymysql和sqlalchemy…...

【算法】排序
排序算法在信息学非常常用。Hello!大家好,我是学霸小羊,今天讲几个排序算法。 1.“打擂台”排序 思路:a[ i ]和a[ j ]打擂台(i<j)。 这个方法简单易懂,只需要看看需不需要交换。按从大到小…...

前端开发之xlsx的使用和实例,并导出多个sheet
前端开发之xlsx的使用和实例 前言效果图1、安装2、在页面中引用3、封装工具类(excel.js)4、在vue中使用 前言 在实现业务功能中导出是必不可少的功能,接下来为大家演示在导出xlsx的时候的操作 效果图 1、安装 npm install xlsx -S npm inst…...
创建数据库数据插入、更新与删除
创建数据库和创建表 一、实验目的 (1)熟悉和掌握数据库的创建和连接方法; (2)熟悉和掌握数据库表的建立、修改和删除; (3)加深对表的实体完整性、参照完整性和用户自定义完整性的…...

【CTF Web】CTFShow web3 Writeup(SQL注入+PHP+UNION注入)
web3 1 管理员被狠狠的教育了,所以决定好好修复一番。这次没问题了。 解法 注意到: <!-- flag in id 1000 -->但是拦截很多种字符。 if(preg_match("/or|\-|\\|\*|\<|\>|\!|x|hex|\/i",$id)){die("id error"); }使用…...

常见API(JDK7时间、JDK8时间、包装类、综合练习)
一、JDK7时间——Date 1、事件相关知识点 2、Date时间类 Data类是一个JDK写好的Javabean类,用来描述时间,精确到毫秒。 利用空参构造创建的对象,默认表示系统当前时间。 利用有参构造创建的对象,表示指定的时间。 练习——时间计…...
Docker数据卷(volume)
数据卷 数据卷是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。(容器内目录与宿主机目录对应的桥梁,修改宿主机对应的目录,docker会映射到容器内部,相当于修改了容器内的,反之也一样)数…...

30.哀家要长脑子了!---栈与队列
1.388. 文件的最长绝对路径 - 力扣(LeetCode) 其实看懂了就还好 用一个栈来保存所遍历过最大的文件的绝对路径的长度,栈顶元素是文件的长度,栈中元素的个数是该文件目录的深度,非栈顶元素就是当时目录的长度 检查此…...

多重继承引起的二义性问题和虚基类
多重继承容易引起的问题就是因为继承的成员同名而产生的二义性问题。 例:类A和类B中都有成员函数display和数据成员a,类C是类A和类B的直接派生类 情况一: class A {public:int a;void display(); }; class B {public:int a;void display; }; class C:…...
ciscn
ciscn Crypto部分复现 古典密码 先是埃特巴什密码(这个需要进行多次测试),然后base64,再栅栏即可 答案:flag{b2bb0873-8cae-4977-a6de-0e298f0744c3} _hash 题目: #!/usr/bin/python2 # Python 2.7 (6…...

智能的PHP开发工具PhpStorm v2024.1全新发布——支持PHPUnit 11.0
PhpStorm是一个轻量级且便捷的PHP IDE,其旨在提高用户效率,可深刻理解用户的编码,提供智能代码补全,快速导航以及即时错误检查。可随时帮助用户对其编码进行调整,运行单元测试或者提供可视化debug功能。 立即获取PhpS…...

Vue2+Element 封装评论+表情功能
有需要的小伙伴直接拿代码即可,不需要下载依赖,目前是初始版本,后期会进行代码的优化。 评论组件如下: 创建 comment.vue 文件。 表情组件 VueEmoji.vue 在评论组件中使用。 <template><div class"comment"…...
【k8s】存储 pvc 参数列表
相关文章: 【K8s】初识PV和PVC 【k8s】存储 pv 参数列表 【k8s】存储 pvc 参数列表 1. pv概述 2. 参数列表 [rootpaas-controller-3:/home/ubuntu]$ kubectl explain pvc.spec KIND: PersistentVolumeClaim VERSION: v1RESOURCE: spec <Object>DESCRI…...

数据集007:垃圾分类数据集(含数据集下载链接)
数据集简介 本数据拥有 训练集:43685张; 验证集:5363张; 测试集:5363张; 总类别数:158类。 部分代码: 定义数据集 class MyDataset(Dataset):def __init__(self, modetrain, …...

Spring常用注解(超全面)
官网:核心技术SPRINGDOC.CN 提供 Spring 官方文档的翻译服务,可以方便您快速阅读中文版官方文档。https://springdoc.cn/spring/core.html#beans-standard-annotations 1,包扫描组件标注注解 Component:泛指各种组件 Controller、…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...