数据结构——栈的讲解(超详细)

前言:

  小编已经在前面讲完了链表和顺序表的内容,下面我们继续乘胜追击,开始另一个数据结构:栈的详解,下面跟上小编的脚步,开启今天的学习之路!

目录

 1.栈的概念和结构

 1.1.栈的概念

 1.2.栈的结构

  

2.栈的实现 (此实现是基于顺序表实现的)

 2.1.栈的初始化

 2.2.栈的销毁

 2.3.入栈

 2.4.出栈

 2.5.取出栈顶的元素

 2.6.判断栈中有效的数据个数

 2.7.栈元素的打印

3.代码展示

 3.1.Stack.h

  3.2.Stack.c

总结 


正文:

 1.栈的概念和结构

 1.1.栈的概念

  栈是一种特殊的线性表,它只允许一端进一端出,只允许在固定的一端去删除数据和插入数据,对于进行插入和删除操作的地方叫做栈顶,另一端叫做栈底,栈中的数据元素遵从后进先出LIFO的原则,简单来说就是最后一个进的最先出来,这和它的结构有关,下面我们来看一下栈的结构

 1.2.栈的结构

  

  上图就是栈的结构图,小编在概念也说过,栈是有栈顶和栈底的,栈顶就是一个出入口,所以我们可以把栈看做成一个罐子,数据只可以从栈顶进行进入和出去,以上就是关于栈的概念和结构了,光知道栈的结构是概念是不够的,下面小编讲带领大家去实现一个栈!

2.栈的实现 (此实现是基于顺序表实现的)

  在讲一些栈的功能之前,由于栈是一种线性表,所以我们实现栈的可以有顺序表,链表两种方式来实现,由于时间复杂度等的原因,小编在这里选择用顺序表实现,但这并不代表着我们不可以用链表实现,小编曾经做过题,那个题就让我们用链表来实现栈,可千万不要以为栈只能用顺序表实现,这是重点!下面小编先给各位栈结构体的内容:

typedef int STDataType;
typedef struct stack {STDataType* arr;   //数组,类型可能不是一定的所以用typedef替换一下int capacity;  //总空间大小int top;      //栈顶表示
}ST;

 2.1.栈的初始化

  我们在每次写一个线性表之前,初始化是必备的操作,因为栈是基于顺序表实现的,所以初始化也顺序表类似,首先我们需要把数组指针先设置为空,对于总空间大小和栈元素个数(栈顶)都得设置为0,由于难度不大,小编就不给各位图演示了,直接上代码:

void STInit(ST* ps)
{ps->arr = NULL;ps->capacity = ps->top = 0;  //总空间个数和有用空间个数都初始化为0
}

 2.2.栈的销毁

  有了初始化操作,自然而然就有着销毁操作,毕竟“有始有终” ,栈的销毁同样也是不难的,我们对于arr,需要判断它是否开辟了空间,如果开辟了就free掉,没有开辟就直接把栈的空间大小和栈顶都置为空就好,下面直接上代码图:

void STDestroy(ST* ps)
{if (ps -> arr)   //先判断是否进行动态内存开辟了{free(ps -> arr);}ps->capacity = ps->top = 0;
}

 2.3.入栈

  在进行完初始化操作以后,就要进行一些正式操作了,看着入栈这个名字很高大尚,以小编的话来说这其实就是栈的尾插(栈也只能尾插,因为只能从栈顶插入),就类似下图:

  上面这个图就展示了入栈操作,其实就是我们在顺序表阶段写的尾插操作,首先我们需要先设置一个函数,来判断一下栈的总空间大小和栈顶是否是相等,如果相等了那就扩容,这个和顺序表的扩容是一样的,详情可以看小编之前写的那一篇,由于栈的插入只有入栈这一种,所以扩容操作直接写到函数内部就好,我们在进行完插入以后,直接往栈顶插入数据,然后让栈顶在想后走一步就好了,下面直接展示代码:

void STPush(ST* ps, STDataType x)   //类似顺序表的尾插
{if (ps->capacity == ps->top){int newcaopacity = ps->capacity == 0 ? 4 : 2 * ps -> capacity;STDataType* arr1 = (STDataType*)realloc(ps->arr, newcaopacity * sizeof(STDataType));assert(arr1);ps->arr = arr1;ps->capacity = newcaopacity;}  //扩容完成ps->arr[ps->top++] = x;
}

 2.4.出栈

  有入栈肯定就会有出栈,对于栈的出栈,其实就是顺序表的尾删操作,因为栈的元素只能从栈顶出,栈底是不可以出元素的,可以类比下图进行记忆:

  通过上图我们就可以知道出栈到底是什么东西,对于出栈,我们首先需要判断栈是不是空的,不然拿什么来出栈?所以此时我们得写一个布尔类型函数来判断一下此时的栈是否是空的,如果是空的返回true,不是真的返回false,此时我们进需要判断栈顶是否为0就好,下面小编直接给代码图:

bool panduan(ST * ps)
{assert(ps);return ps -> top == 0;   //这个是来判断栈是不是空了
}

  对于上面的代码,小编其实写的很简略,其实如果写麻烦一点我们需要使用选择语句来判断一下是否为空,这里小编直接使用一句话来跳过选择语句了,这个代码的含义就是如果右边是对的那么直接返回true,如果栈顶不为0直接返回false。当我们判断完以后,可以直接进行尾删操作,很简单,我们只需呀让栈顶减一就好了,此时我们就实现了出栈操作,下面给出代码图:

void STPop(ST* ps)
{assert(ps);assert(!panduan(ps));ps->top--;
}

 2.5.取出栈顶的元素

  这个也是很轻松的,对于取出栈顶的元素,其实就是取顺序表(或者可以直接理解为数组)最后一个有效数据,此时我们还是需要判断栈顶是否还有元素,如果有的话我们直接取出来就好了,可是如果那我们就取出了个寂寞,所以这一步是必须的,之后我们就直接返回栈的最后一个有效数据就好了,下面是代码展示:

STDataType STTop(ST* ps)
{return ps->arr[ps->top - 1];
}

 2.6.判断栈中有效的数据个数

  这个其实说白了,就是返回栈顶的元素就好了,此时我们也不需要在判断栈是否有数据了,如果没有数据,那就直接返回0就好,下面小编就直接展示代码了:

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

 2.7.栈元素的打印

  对于栈中元素的打印,其实也是有点要求的,可能有些读者朋友会说,我们直接从头打印不就好了,那当然是不行的,这样就违背了我们栈的结构,我们只能从栈顶进入和出去,所以我们打印数据其实就是从栈顶开始进行打印的,我们每进行完一次打印后就让栈顶元素出栈,直到栈中的元素为空就好了,如下图所示:

   正如上图所示,打印操作也是这么实现,下面进入代码展示:

void print(ST * ps)
{while (ps.top){printf("%d ", STTop(&ps));STPop(&ps);}
}

  以上就是栈结构的实现,其实这么看去,栈是一种比较简单实现的数据结构了(前提学完了顺序表),可能有一些读者朋友想要知道完整的代码,不要着急,下面进入代码展示环节!

3.代码展示

  对于栈的实现,小编也是分成了两个文件来进行书写,一个用来声明函数,一个用来实现函数:

 3.1.Stack.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>   //存放布尔类型的头文件//下面来复习一下栈的创建  
//它的底层代码是数组(也可以理解为顺序表)
typedef int STDataType;
typedef struct stack {STDataType* arr;   //数组,类型可能不是一定的所以用typedef替换一下int capacity;  //总空间大小int top;      //栈顶表示
}ST;//初始化栈
void STInit(ST* ps);//销毁栈
void STDestroy(ST* ps);//入栈
void STPush(ST* ps, STDataType x);//出栈
void STPop(ST* ps);//取出栈顶的元素
STDataType STTop(ST* ps);//获取栈中有效的个数
int STSize(ST* ps);

  3.2.Stack.c

#include"Stack.h"
void STInit(ST* ps)
{ps->arr = NULL;ps->capacity = ps->top = 0;  //总空间个数和有用空间个数都初始化为0
}void STDestroy(ST* ps)
{if (ps -> arr)   //先判断是否进行动态内存开辟了{free(ps -> arr);}ps->capacity = ps->top = 0;
}void STPush(ST* ps, STDataType x)   //类似顺序表的尾插
{if (ps->capacity == ps->top){int newcaopacity = ps->capacity == 0 ? 4 : 2 * ps -> capacity;STDataType* arr1 = (STDataType*)realloc(ps->arr, newcaopacity * sizeof(STDataType));assert(arr1);ps->arr = arr1;ps->capacity = newcaopacity;}  //扩容完成ps->arr[ps->top++] = x;
}bool panduan(ST * ps)
{assert(ps);return ps -> top == 0;   //这个是来判断栈是不是空了
}void STPop(ST* ps)
{assert(ps);assert(!panduan(ps));ps->top--;
}STDataType STTop(ST* ps)
{return ps->arr[ps->top - 1];
}int STSize(ST* ps)
{return ps->top;
}

总结 

  小编也是完成了对于栈的讲解,总体来说,栈这个数据结构小编自己认为是不算太难的(关于栈的习题不算),本篇文章算是小编最近写的最短的一篇了,希望读者朋友可以去好好的了解,如果文章有什么错误的地方,请在评论区指出,小编一定及时更正,那么我们下篇文章见啦!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vatee万腾平台:数据智能的创新引擎,引领企业数字化转型新纪元

在数字化转型的浪潮中&#xff0c;企业正以前所未有的速度重构着自身的运营模式与核心竞争力。作为这一变革的领航者&#xff0c;Vatee万腾平台凭借其卓越的数据智能能力&#xff0c;正逐步揭开企业数字化转型的新篇章。本文将深入探讨Vatee万腾平台如何以数据为核心&#xff0…

【多线程基础】进程和线程的区别和联系(重要)

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;Java多线程 &#x1f4da;本系列文章为个人…

【JavaEE】CAS原理

目录 ​前言 什么是CAS&#xff1f; 如何使用CAS&#xff1f; CAS实现自旋锁 CAS的ABA问题 面试题 1.讲解下你自己理解的CAS机制 2.ABA问题怎么解决&#xff1f; 前言 在多线程中&#xff0c;多个线程同时对一个共享变量进行读写操作&#xff0c;那么就会出现线程安全问…

01 NoSQL之Redis配置与优化

目录 1.1 Redis介绍 1.1.1关系数据库与非关系型数据库 1 . 关系型数据库 2. 非关系型数据库 3.非关系型数据库产生背景 (1) High performance--对数据库高并发读写需求 &#xff08;2) Huge Storage--对海量数据高效存储与访问需求 &#xff08;3) High Scalability …

gitlab cicd快速入门有哪些方法 gitlabcicd和Jenkins哪个更好用

在现代软件开发中&#xff0c;持续集成和持续交付&#xff08;CI/CD&#xff09;已成为必不可少的流程。它们不仅能提高开发效率&#xff0c;还能保证代码的质量和稳定性。在众多CI/CD工具中&#xff0c;GitLab和Jenkins是最为常用的两种。本文将围绕“gitlab ci/cd快速入门有哪…

vuex properties of undefined (reading ‘getters‘)

前言&#xff1a; 最近打算用vue 写个音乐播放器&#xff0c;在搞 vuex 的时候遇到一个很神奇报错&#xff1b;vuex 姿势练了千百次了&#xff0c;刚开始的时候我一直以为是代码问题&#xff0c;反复检查了带了&#xff0c;依旧报错。 Error in mounted hook: "TypeError:…

[Android] [解决]Bottom Navigation Views Activity工程带来的fragment顶部空白间距问题

用Android Stuio创建一个Bottom Navigation Views Activity工程&#xff0c; 我们刻意设置一下fragment背景为黑色&#xff0c;会发现&#xff0c;这个fragment离顶部还有一段不小空白距离&#xff0c; 怎么解决呢&#xff1f; 在activity_main.xml里面&#xff0c;删掉这句&a…

极狐GitLab安全版本:16.10.1、16.9.3、16.8.5

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

数据结构之线性表(单链表的实现)

目录 一、单链表的原理 二、单链表的实现 1.单链表的定义 2.单链表的初始化 3.清空单链表 4.单链表是否为空 5.单链表的长度 6.获取指定位置 i 的元素 7.获取指定元素 e 的位置 8.向链表中插入指定位置的元素 9.向链表中删除指定位置的元素 10.遍历链表中的元素 …

告别手动操作!KeyMouseGo实现自动化工作流

前言 在这个快节奏的时代&#xff0c;我们每天都在与电脑打交道&#xff0c;重复着那些繁琐而单调的操作&#xff1b;你是否曾想过&#xff0c;能让电脑自己完成这些任务&#xff0c;而你则悠闲地喝着咖啡&#xff0c;享受着生活&#xff1f;今天&#xff0c;就让我们一起揭开一…

【sdk】- 对接阿里云抠图

文档地址&#xff1a;https://help.aliyun.com/zh/viapi/use-cases/general-image-segmentation?spma2c4g.11186623.0.0.3814173cenldIs java对接阿里云的通用分割&#xff0c;将代码原封不动复制进来&#xff0c;执行结果失败&#xff0c;咨询阿里云的人员之后&#xff0c;由…

优盘数据救援:应对文件与目录损坏的全方位指南

一、问题剖析&#xff1a;优盘文件或目录损坏的困境 在数字化时代&#xff0c;优盘&#xff08;USB闪存驱动器&#xff09;作为便携、高效的数据存储工具&#xff0c;广泛应用于数据传输、备份与分享。然而&#xff0c;面对频繁的使用与不当操作&#xff0c;优盘中的文件或目录…

FPGA常见型号

FPGA&#xff08;现场可编程门阵列&#xff09;开发板种类繁多&#xff0c;涵盖了从入门级教育用途到高性能工业应用的广泛领域。以下是一些常见的 FPGA 开发板型号及其特点&#xff1a; 1. Xilinx&#xff08;赛灵思&#xff09;系列 Xilinx 是 FPGA 领域的领导者之一&#…

Ubuntu22.04安装Docker教程

简介 ​ Docker 是一个开源的平台&#xff0c;旨在简化应用开发、交付和运行的过程。通过使用容器技术&#xff0c;Docker 能够让开发人员将应用及其依赖环境一同打包&#xff0c;从而实现快速部署、一致的开发环境和优秀的可移植性。 系统版本 ​ 本文以Ubuntu 22.04.4 LTS…

【探索Linux】P.46(高级IO —— 五种IO模型简介 | IO重要概念)

阅读导航 引言一、五种IO模型1. 阻塞IO&#xff08;1&#xff09;定义&#xff08;2&#xff09;特点 2. 非阻塞IO&#xff08;1&#xff09;定义&#xff08;2&#xff09;特点 3. IO多路复用&#xff08;1&#xff09;定义&#xff08;2&#xff09;特点 4. 信号驱动IO&#…

深入探索:【人工智能】、【机器学习】与【深度学习】的全景视觉之旅

目录 第一部分&#xff1a;人工智能、机器学习与深度学习概述 1.1 人工智能的概念与发展 代码示例&#xff1a;简单的AI决策系统 1.2 机器学习的定义与分类 代码示例&#xff1a;简单的线性回归模型 1.3 深度学习的基础与应用 代码示例&#xff1a;构建简单的神经网络 …

【TwinCAT】TwinCAT3 PLC HMI在WIN10系统中的全屏显示及用户管理

在工业自动化领域,TwinCAT3 PLC HMI 是一款强大的可视化工具,它支持多种操作系统,并且能够满足不同控制器的需求。在本文中,我们将详细介绍如何在WIN10系统中进行全屏显示设置以及如何进行用户管理配置。 一、TwinCAT3 PLC HMI 全屏显示方法 1. 创建Visualization和配置Vi…

Git开发流程

Git开发流程规范如下&#xff1a; 详情参考&#xff1a;https://www.processon.com/view/link/5d0cf86ce4b0376de9c19e16

【自动驾驶】ROS中自定义格式的服务通信,含命令行动态传参(c++)

目录 通信流程创建服务器端及客户端新建服务通讯文件修改service的xml及cmakelistCMakeLists.txt编辑 msg 相关配置编译消息相关头文件在cmakelist中包含头文件的路径在service包下编写service.cpp在client包下编写client.cpp测试运行查询服务的相关指令列出目前的所有服务&…

【Vue3】组件通信之mitt

【Vue3】组件通信之mitt 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日…