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

news2024/9/22 4:04:59

前言:

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

目录

 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.coloradmin.cn/o/2034576.html

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

相关文章

redis面试(十五)公平锁队列重排

队列重拍 先说一下当前的加锁状态 anyLock由客户端A持有队列中是客户端B、客户端C并且客户端B现在是排在头部 那么队列重拍就是队列中某个客户端长时间没有重新申请加锁&#xff0c;没有刷新分数&#xff0c;就会被队列中挤掉。 假设这个长时间没有加锁的客户端是B。 总结 …

C++ CMake FFmpeg配置

SDK下载 github 环境变量配置 cmake_modules/FindFFmpeg.cmake # This module defines the following variables: # # FFmpeg_FOUND - All required components and the core library were found # FFmpeg_INCLUDE_DIRS - Combined list of all components includ…

Dijkstra单源最短路径算法学习有感

认识Dijkstra 艾兹格维布迪克斯特拉&#xff08;Edsger Wybe Dijkstra&#xff0c;/ˈdaɪkstrə/ DYKE-strə&#xff1b;荷兰语&#xff1a;[ˈɛtsxər ˈʋibə ˈdɛikstra] 1930年5月11日-2002年8月6日&#xff09;是一位荷兰计算机科学家、程序员、软件工程师、系统科学…

(回溯) LeetCode 46. 全排列

原题链接 一. 题目描述 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a;…

零基础学习Redis(1) -- Redis简介

Redis是一个在内存中存储数据的一个中间组件&#xff0c;可用作数据库或数据缓存&#xff0c;通常在分布式系统中使用 &#xff08;不了解分布式&#xff1f; 点击传送&#xff09; 1. Redis特性 在内存中存储数据&#xff0c;通过键值对的方法存储key为string&#xff0c;v…

[GYCTF2020]FlaskApp1

打开题目 简单的一个base64加解密小程序 查看提示&#xff0c;好像并没有什么用&#xff0c;题目是flask&#xff0c;可能是ssti模板注入 加密窗口{{77}},解密窗口e3s3Kzd9fQ ({{77}} 加密窗口没看到注入&#xff0c;解密窗口存在注入&#xff0c;是模板注入 读取文件内容&am…

JimV私有云平台部署及应用

1. JimV概述 1.1 介绍 JimV 是一个&#xff0c;结构精简&#xff0c;易于部署、维护、使用的&#xff0c;企业私有云管理平台。JimV 基于 KVM 开发而来&#xff0c;通过 JimV 管理平台&#xff0c;可以批量创建、管理虚拟机。 JimV 更为轻量级&#xff0c;使用户轻易拥有维护…

【Day05】0基础微信小程序入门-学习笔记

文章目录 基础加强学习目标使用npm包1.准备项目2. 小程序对于npm的支持和限制3. Vant Weapp小程序UI组件库4. 使用Vant组件5. 定制全局主题样式6. API Promise化 全局数据共享1. 简介2. MobX2.1 安装MobX相关包并构建npm2.2 创建MobX的Store实例2.3 将Store成员绑定到页面中2.4…

SpringBoot统一功能

目录 前言1&#xff1a;首先要明白&#xff0c;什么是统一功能&#xff1f; 前言2&#xff1a;统一功能包括哪些呢&#xff1f;展开说说&#xff1f; 一、拦截器&#xff08;interceptor&#xff09; 1、介绍 2、如何使用拦截器 3、拦截器的在程序内部的执行流程是啥呢&a…

MySQL关键字—using和on

文章目录 1. MySQL关键字—using和on1.1 using关键字的概念 2. using和on的区别2.1 USING 子句2.2 ON 子句 3. 示例对比3.1 建表&#xff1a;3.2 准备数据3.3 结果 1. MySQL关键字—using和on 1.1 using关键字的概念 连接查询时如果是同名字段作为连接条件&#xff0c;using可…

ctfhub Bypass disable_function(完结)0

LD_PRELOAD url 蚁剑连接 选择插件 点击开始 查看到此文件名编辑连接拼接到url后面重新连接 点击开启终端 在终端执行命令 ls / /readfile ShellShock url CTFHub 环境实例 | 提示信息 蚁剑连接 写入shell.php <?phpeval($_REQUEST[ant]);putenv("PHP_test() { :…

四款AI写作免费工具,让文案工作更轻松

作为一名文案编辑&#xff0c;我算是跟文字打了几年的交道了。最近&#xff0c;AI写作这股风潮真是吹得热火朝天&#xff0c;我也忍不住尝了尝鲜&#xff0c;试了试几款神器。说实话&#xff0c;这体验还挺有意思的&#xff0c;感觉就像是在文字的世界里开了一场高科技的派对。…

Redis:概念、部署、配置、优化

目录 关系型数据库与非关系型数据库 关系型数据库 非关系型数据库 非关系型数据库存在的原因 Redis 概念 优点 Redis部署流程 初步设置 安装 初始化 初始化时指定的参数说明 Redis配置文件 修改监听地址 Redis远程连接 远程连接 测试服务端状态 redis-benchm…

智慧景区系统:科技赋能旅游新体验

随着信息技术的飞速发展&#xff0c;旅游业正经历着前所未有的变革&#xff0c;智慧景区系统作为这一变革的先锋&#xff0c;正以其独特的魅力重塑着游客的旅行方式。智慧景区系统&#xff0c;顾名思义&#xff0c;是运用物联网、大数据、云计算、人工智能等现代信息技术&#…

Git客户端 TortoiseGit下载

1.概述 使用TortoiseGit比直接使用git客户端和命令来实现代码管理更为方便&#xff0c;本文贴出了软件的下载地址和基本配置信息 2.TortoiseGit安装与配置 TortoiseGit是TortoiseSVN的Git版本&#xff0c;是一个在Windows系统下使用的Git版本控制客户端。它提供了图形用户界…

MIT线性代数P5

置换矩阵 置换矩阵是行重新排列的单位矩阵。 置换矩阵用P表示&#xff0c; 性质&#xff1a; n阶置换矩阵共有n!个

37.x86游戏实战-XXX遍历怪物数组

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

0812|TCP和UDP跨主机通信

思维导图 TCP实现跨主机通信 服务器端 #include<myhead.h> #define SER_PORT 6666 //端口号 #define SER_IP "192.168.0.108" //服务器IP int main(int argc, const char *argv[]) {//创建套接字文件int sfd socket(AF_INET,SOCK_STREAM,0);if(sfd -1){pe…

进阶!haproxy高级功能与配置

文章目录 前言基于cookie的会话保持IP透传四层IP透传未开启状态开启透传状态 七层IP透传 自定义错误界面重定向HAProxy 四层负载之数据库HAProxy https 前言 本文主要介绍HAProxy高级配置及使用案例 文章相关连接如下&#xff1a; 如果想深入了解haproxy算法的相关知识&…

基于Python+Django+Vue+Mysql前后端分离的图书管理系统

利用空闲休息时间开始自己写了一套图书管理系统。现将源码开源&#xff0c;项目遇到问题 PythonDjangoVue图书管理系统开发全流程 大家好&#xff0c;我是程序员科科&#xff0c;这是我开源的基于PythonDjangoVue的图书管理系统 希望可以帮助想学前后端分离的同学 项目中遇…