数据结构之栈的超详细讲解

目录

引言

一.栈的概念

二.栈的结构

三.栈的实现

栈结构的实现

栈操作函数的声明

栈中方法的实现

栈的初始化

栈的销毁

入栈

出栈

取栈顶元素

判断栈中是否为空

获取栈中数据个数

四.测试 

代码展示:

结构展示:

五.小结

六.完整代码

Stack.h

Stack.c

text.c


引言

这个专题是专门对栈进行详细的讲解,栈这个数据结构其实和之前的顺序表和单链表一样,同样是线性结构,但它的限制更大,如果想看之前单链表和顺序表数据结构的实现,或者是之后的数据结构我现在还没出的,都可以订阅我这个数据结构初阶的专栏--http://t.csdnimg.cn/sz4xS.好了,话不多说,点赞关注我们开始!

一.栈的概念

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

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。 

栈这个数据结构可以总结为四个字:后进先出

二.栈的结构

因为栈也是一种线性结构,所以并不复杂,如下图所示:

栈这种结构在我们生活中其实并不少见,比如我们打羽毛球用的羽毛球桶,装子弹的弹匣,都满足后进先出的一个特性. 

三.栈的实现

栈结构的实现

我们可以用三种方法实现栈这个结构:

方法一:

我们用双向链表构建栈,如下图所示:

这样做的好处是:双向链表能很轻松的寻找前面的节点

方法二:

我们用单链表构建栈,如下图所示:

我们用单链表构建栈时,我们入栈时需要头插,因为单链表找前面的节点是不好找的

方法三:

我们用动态数组构建栈:

这个方法就类似于基于动态数组构建顺序表

那么这三种方法选择哪一种呢?

首先因为单链表的原因,我们先把双向链表PASS掉

接下来就在单链表和动态数组中选择

其实两者相差不大,但由于动态数组具有元素高效率存储,所以这里选择动态数组实现栈

代码展示:

//栈的结构
typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

 注意:这里的STDataType和之前的链表和顺序表一样,方便后面进行类型的替换

a时我们的动态数组

top是我们的栈顶指针

capacity是我们的空间容量

栈操作函数的声明

对于线性表来说,操作函数大同小异,所以栈的操作函数其实跟单链表和顺序表差不多

下面便是操作函数的声明:

//函数的声明
//初始化和销毁
void STInit(ST* pst);
void STDestory(ST* pst);
//入栈和出栈
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
//取栈顶元素
STDataType STTop(ST* pst);
//判空
bool STEmpty(ST* pst);
//获取数据个数
int STSize(ST* pst);

栈中方法的实现

栈的初始化

注意:

栈这里的初始化分为两种方式:

1.top指向-1,top指向栈顶元素,如下图所示:

注意:这里的top不能指向为0,因为这样的话,当top指为0时,不知道是否含有数据

2.top指向0,top指向栈顶元素的下一位,如下图所示:

这里我用了第二种,因为这里的top即为元素个数,对于后面的操作会方便一点.

//初始化和销毁
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	//top指向栈顶数据的下一个位置
	pst->top = 0;

	//top指向栈顶数据
	//pst->top = -1;
	pst->capacity = 0;
}

栈的销毁

void STDestory(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

注意最后要将top和capacity置为0

入栈

和顺序表的插入数据类似,首先进行断言处理,再看空间是否够用,不够用就进行两倍扩容.

注意:这里使用了三目操作符,因为我们初始化capacity为0,两倍扩容之后还是为0,所以当它为0时,直接初始化为4,或者其他值.

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapcacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapcacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapcacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

出栈

这个很简单,只需top--即可

void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}

取栈顶元素

注意:这里需要额外对top进行判空处理

//取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	return pst->a[pst->top - 1];
}

判断栈中是否为空

top即为我们栈中元素的个数

//判空
bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}

获取栈中数据个数

//获取数据个数
int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

四.测试 

我们入栈一些元素,再将它们打印出来.

代码展示:

#include "Stack.h"

int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	//遍历栈中的元素
	while (!STEmpty(&s))
	{
		printf("%d ", STTop(&s));
		STPop(&s);
	}

}

结构展示:

后进先出没有问题

五.小结

栈这个数据结构对比顺序表和单链表的实现真的简单了不少,但它的OJ题可不简单,后面我会更新关于栈的经典OJ练习,如果觉得这篇博客对你有帮助的话,一定要点赞关注哦!如果你有任何问题后可以打在评论区,大家一起学习,共同进步!

六.完整代码

Stack.h

#pragma once
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//栈的结构
typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

//函数的声明
//初始化和销毁
void STInit(ST* pst);
void STDestory(ST* pst);
//入栈和出栈
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
//取栈顶元素
STDataType STTop(ST* pst);
//判空
bool STEmpty(ST* pst);
//获取数据个数
int STSize(ST* pst);

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

//初始化和销毁
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	//top指向栈顶数据的下一个位置
	pst->top = 0;

	//top指向栈顶数据
	//pst->top = -1;
	pst->capacity = 0;
}
void STDestory(ST* pst)
{
	assert(pst);

	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 newcapcacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapcacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapcacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(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 STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}
//获取数据个数
int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

text.c

#include "Stack.h"

int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	//遍历栈中的元素
	while (!STEmpty(&s))
	{
		printf("%d ", STTop(&s));
		STPop(&s);
	}

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安卓手机平板使用Termux+Hexo搭建本地博客站点并实现无公网IP远程访问

文章目录 前言1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址 前言 本文主要介绍如何在安卓手机平板Termux中安装个人hexo博客并结合cpolar内网穿透工具&#xff0c;实现远程访问本地搭建的博客站点&#xff0c;无需公网IP。 Hexo 是一个用 Nodejs 编写的快速、简洁且高效…

STM32的ADC详解

ADC即模拟数字转换器&#xff0c;通常用于将外部的模拟量信号转换为数字信号。STM32的ADC是12位逐次逼近型的模拟数字转换器&#xff0c;最大可以计数到4095&#xff0c;有18个通道&#xff0c;16个外部通道和2个内部通道。 ADC框图 ADC的功能框图可以分为七个部分&#xff1a…

6个让你的活动策划成倍回报的策略-华媒舍

活动策划是一个集思广策、全方位考虑的过程&#xff0c;只有通过科学合理的策略规划&#xff0c;才能在有限的资源下取得最大的回报。本文将分享六个让你的活动策划成倍回报的策略&#xff0c;包括目标设定、策划团队、预算控制、宣传推广、参与体验和后期回顾。 1. 目标设定 …

基于LMV358的负电源架构

嘿UU们&#xff0c;中午好啊&#xff01;吃了没&#xff1f;算算时间我的餐桌上应该快上杨梅和鱼胶冻了。 今天看某群&#xff0c;突然想到Jim williams的书里一个架构&#xff0c;但老爷子的东西是正负输出的&#xff0c;而且略微有点麻烦&#xff0c;我就想怎么样整个更适合…

【小笔记】streamlit使用笔记

【小笔记】streamlit使用笔记 1.streamlit是什么&#xff0c;为什么要用它&#xff1f; 一句话&#xff0c;这个东西是一个python的可视化库&#xff0c;当你想要给你的程序添加个web界面&#xff0c;而又不会或不想用前端技术时&#xff0c;你就可以考虑用它。 类似的可视化库…

论文AI率太高怎么办?笔灵aigc去痕AIGC率直降60%

随着 AI 技术迅猛发展&#xff0c;各种AI辅助论文写作的工具层出不穷&#xff01; 为了防止有人利用AI工具进行论文代写&#xff0c;在最新的学位法中已经明确规定“已经获得学位者&#xff0c;在获得该学位过程中如有人工智能代写等学术不端行为&#xff0c;经学位评定委员会…

初识Java的main方法

创建一个Java文件 main方法以及用cmd运行程序的过程 面试题JDK\JRE\JVM之间的关系 注意事项 解析String[ ] args 我们想知道String[ ] args里面到底是什么&#xff0c;我们可以用for循环遍历这个数组 Java代码结构 编写Java程序时可能会遇见的错误 注释 注释是为了让代码更…

音频系统模块级实验

加zkhengyang进数字音频系统研究开发交流答疑群(课题组) 1 购买ADC-I2S模块&#xff0c;购买I2S-DAC模块 进行音频系统搭建&#xff0c;可加深对i2s音频总线的理解 2 用电脑的音频输出进行实验

[JAVASE] 类和对象(一)

目录 一.类的基本定义 1.1 类与对象 1.2 类的定义 二. 类的实例化 2.1 创建引用 三. 类中成员的访问 3.1 基本实现 3.2 this引用 四. 构造与初始化 4.1 初始化 4.2 构造方法 五. 总结 一.类的基本定义 1.1 类与对象 类对应着对象 1.2 类的定义 二. 类的实例化 2.1 创建引用…

WPS被指套娃式收费!我快用不起免费的中国互联网了……

接触互联网二十余年&#xff0c;小柴发现&#xff0c;中国互联网与国外互联网有一个很大的区别。 即国外的互联网一般都是收费的&#xff0c;比如杀毒软件、办公软件&#xff0c;以及下载各种APP、游戏&#xff0c;看个视频&#xff0c;基本上都是要单独付费购买的&#xff0c…

2024华为数通HCIP-datacom最新题库(变题版)

请注意&#xff0c;华为HCIP-Datacom考试831已变题 请注意&#xff0c;华为HCIP-Datacom考试831已变题 请注意&#xff0c;华为HCIP-Datacom考试831已变题 近期打算考HCIP的朋友注意了&#xff0c;如果你准备去考试&#xff0c;还是用的之前的题库&#xff0c;切记暂缓。 H1…

Linux(CentOS7)离线使用安装盘部署Telnet

[在线工具网 - 各类免费AI工具合集&#xff0c;免费pdf转word等](https://www.orcc.online) https://orcc.online 挂载镜像CentOS-7-x86_64-DVD-1810.iso到/mnt下&#xff08;其他位置也行&#xff09;&#xff0c;命令如下&#xff1a; mount /dev/sr0 /mnt 安装包默认在Pa…

RabbitMQ是怎么做消息分发的?——Java全栈知识(14)

RabbitMQ是怎么做消息分发的&#xff1f; RabbitMQ 的消息分发分为五种模式&#xff1a;分别是简单模式、工作队列模式、发布订阅模式、路由模式、主题模式。 1、简单模式 publisher 直接发送消息到队列消费者监听并处理队列中的消息 简单模式是最基本的工作模式&#xff0c;…

ubuntu中的docker记录(5)——如何使用阿里云的镜像加速配置docker镜像加速器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、镜像加速器介绍1. 什么是docker镜像加速器&#xff1f;2. 为什么要配置镜像加速器&#xff1f; 二、配置镜像加速器1. 注册阿里云账号2. 注册镜像容器服务3…

Go-Zero自定义goctl实战:定制化模板,加速你的微服务开发效率(四)

前言 上一篇文章带你实现了Go-Zero和goctl&#xff1a;解锁微服务开发的神器&#xff0c;快速上手指南&#xff0c;本文将继续深入探讨Go-Zero的强大之处&#xff0c;并介绍如何使用goctl工具实现模板定制化&#xff0c;并根据实际项目业务需求进行模板定制化实现。 通过本文…

CSP-j 计算机硬件

计算机系统 计算机系统由计算机硬件和软件两部分组成。硬件包括中央处理器、存储器和外部设备等&#xff1b;软件是计算机的运行程序和相应的文档。计算机系统具有接收和存储信息、按程序快速计算和判断并输出处理结果等功能。 主要技术指标 字长&#xff1a;字长是指CPU能够同…

浅谈冯诺依曼体系与Linux操作系统

目录 前言 1.1冯诺依曼体系下的存储器 二、操作系统 1.关于操作系统 2.关于管理方式 总结 前言 不知道你是否有着这样的疑问&#xff1a; 什么是内存&#xff1f;什么是磁盘&#xff1f;他们有什么区别&#xff1f;可不可以相互替代&#xff1f; 操作系统是如何对数据进行管…

聚类分析 | 基于GA遗传算法优化kmeans聚类(Matlab)

聚类分析 | 基于GA遗传算法优化kmeans聚类&#xff08;Matlab&#xff09; 目录 聚类分析 | 基于GA遗传算法优化kmeans聚类&#xff08;Matlab&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GA-kmeans聚类算法&#xff0c;通过GA遗传算法优化kmeans聚类&…

vue2实现右键菜单功能——vue-diy-rightmenu——基础积累

五一之前遇到一个需求&#xff0c;就是关于要实现自定义右键菜单的功能&#xff0c;普通的右键展示的菜单有【返回/前进/重新加载/另存为】等&#xff0c;希望实现的效果就是右键出现自定义的菜单&#xff0c;比如【编辑/删除/新增】等。 遇到这种的需求&#xff0c;可以直接去…

C#进阶-OleDb操作Excel和数据库

在C#编程中&#xff0c;使用OleDb可以方便地实现对Excel文件和数据库的操作。本文探讨了在C#中使用OleDb技术操作Excel和数据库的策略。文章详述了OleDb的定义、配置环境的步骤&#xff0c;并通过实际代码示例演示了如何高效读写Excel文件和交互数据库。文中还评估了OleDb技术的…