数据结构学习:栈(详细讲解)

news2024/11/19 2:30:49

🎁个人主页:我们的五年

🔍系列专栏:C语言基本概念 

🌷追光的人,终会万丈光芒

🎉欢迎大家点赞👍评论📝收藏⭐文章

目录

🚗1.对栈概念理解:

🚗2.选择哪种数据结构实现栈:

🎉数组:

🎉链表:

🚗3.栈的几个基本操作函数:

🎉1.栈的初始化:

🎉2.栈的销毁:

🎉3.栈的初始化:

🎉4.取栈顶元素:

🎉5.对栈判空,为空返回true,不为空返回false:

🎉6.销毁栈顶元素:

🎉7.获取栈里面的元素个数:


 前言:

本次让我们来学习栈,以及对前面学习的顺序表和链表进行一个比较。

喜欢的铁子可以支持一下!祝大家天天开心!

🚗1.对栈概念理解:

栈的特点:先进后出。

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

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

栈是和顺序表很像,我觉得是一种特殊的顺序表。栈只允许从一端进行插入和删除(访问一次就等于一次删除,就是出栈),但是可以同时进行插入和删除操作,不一定要把全部的数据入栈以后,再进行出栈。

●现实生活中栈的模型:弹夹,先装进去的子弹后出来,后装进去的子弹先被打出来。

●但是,下面的图形象化,更好理解。

 上面的表示的就是栈只能从一边入,也只能从这一边出数据。但是我可以入一个就出一个。也可以入两个,然后出一个,然后在入栈。

🚗2.选择哪种数据结构实现栈:

我们知道,栈就是一种线性结构,但是前面我们学的线性结构有数组,链表。

🎉数组:

物理(内存)上连续,逻辑上也连续:

数组的顺序存储结构,采用一组连续的内存来存储数据。

数组的线性关系是在内存(物理)上的相邻关系来表示数组的逻辑关系,也就是说,数组的连续和线性依靠的是内存的连续和线性。

●数组内存是连续的,所以可以随机访问,读取效率很高。

●数组在进行插入时,在下表为i的位置之前插入数据,需要把[i,n-1]的数据往后面移动,才能进行插入数据。但是如果在尾部插入就不需要对数组进行移动。

●数组在开辟的时候就要确定大小,如果是动态内存,后面进行增容的时候,还要考虑后面的空间知否足够,如果不足够,还要找一块新的内存,把之前的数据进行拷贝。因为是确定了大小了的,所以有时候会浪费空间。

🎉链表:

物理(内存上不连续,逻辑上连续:

链表是链式存储结构,链表的内存(物理)不一定是连续的,但是逻辑上是连续的。也就是可以通过节点一找到节点二,节点二可以找到节点……

●因为上面这种链式结构,所以链表的读取效率低,要读取数据,要去遍历链表。

●链表只是逻辑连续,所以在进行插入删除时也更方便。不需要对数据进行移动,只需要把新的节点与原来的链表建立联系。

●链表定义的时候,没有确定大小,所以链表的增容也更方便。

根据以上数组和链表的区别,我们可以思考在实现栈的时候,那种数据结构更好,因为栈只能在一端插入删除数据,插入删除数据的时候,只是在尾部进行插入删除,就不要去移动数据位置,这样我们就选择数组实现栈。

🚗3.栈的几个基本操作函数:

和顺序表和链表一样,都是自定义的结构体类型,所以我们要去实现一下它的几个基本函数。比如:栈的初始化,栈的销毁,入栈,出栈……

🎉1.栈的初始化:

//栈的初始化
void StackInit(Stack* ptr)
{
    assert(ptr);
    ptr->a = NULL;
    ptr->capacity = ptr->top = 0;
}

❗️注意:

1.一开始我们把top置为0,也就是说,没有数据的时候,top=0,top和元素个数的大小是一样的。

2.top=0,下次我们要插入数据的时候,也是在下标为0的位置进行插入,所以这是top表示的是栈顶元素的下一位

3.如果我们一开始把top=-1,就表示当前栈顶元素的下标。插入一个元素以后,top=0,插入的数据下标也是0,所以这个时候的top表示栈顶元素的下标。

🎉2.栈的销毁:

//销毁栈
void StackDestroy(Stack* ptr)
{
    assert(ptr);
    free(ptr->a);
    ptr->a = NULL;
    ptr->capacity = ptr->top = 0;    //初始化时,top=0,表示指向栈顶的下一个元素
}

🎉3.栈的初始化:

//在栈顶插入元素
void StackPush(Stack* ptr, SLDataType x)
{
    assert(ptr);
    if (ptr->top == ptr->capacity)
    {
        int newcapacity = ptr->capacity == 0 ? 4 : ptr->capacity * 2;
        SLDataType* tmp = (SLDataType*)realloc(ptr->a, newcapacity*sizeof(SLDataType));
        if (tmp == NULL)
        {
            perror("realloc fail");
            return;
        }
        ptr->a = tmp;
        ptr->capacity = newcapacity;
    }
    ptr->a[ptr->top++] = x;
}

❗️注意:

1.因为我们在栈的初始化的时候,我们没有申请数组大小,所以我们在插入数据在进行判断是否数据已经存满的时候,我们要去考虑数据个数为0的情况。

🎉4.取栈顶元素:

//取栈顶元素
SLDataType StackTop(Stack* ptr)
{
    assert(ptr);
    assert(!StackEmpty(ptr));
    return ptr->a[ptr->top - 1];
}
 

🎉5.对栈判空,为空返回true,不为空返回false:

//栈判空
bool StackEmpty(Stack* ptr)
{
    assert(ptr);
    return ptr->top == 0;
}

🎉6.销毁栈顶元素:

//销毁栈顶元素
void StackPop(Stack* ptr)
{
    assert(ptr);
    assert(!StackEmpty(ptr));

    ptr->top--;
}
 

🎉7.获取栈里面的元素个数:

//获取栈里面元素个数
int StackSize(Stack* ptr)
{
    assert(ptr);

    return ptr->top;
}

说明:

上面有些函数只有一条语句,我们还写成函数的形式,看上去感觉没有必要。但是当我们把我们写的函数给别人用,别人只要调用这些函数就可以了,就不会出错。

比如:没有函数,让别人使用的时候,当别人要去栈顶的元素,别人就不知道到底是top指向栈顶元素的下标,还是top-1是栈顶元素的下标。因为top初始化为0时,top-1指向指向栈顶元素的下标,top初始化为-1时,top指向栈顶元素的下标。

🚗4.栈的总体代码:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

typedef int SLDataType;

typedef struct Stack{
	SLDataType* a;
	int top;
	int capacity;
}Stack;

//对栈进行初始化
void StackInit(Stack* ptr);

//对栈进行销毁
void StackDestroy(Stack* ptr);

//在栈顶插入元素
void StackPush(Stack* ptr, SLDataType x);

//获取栈顶元素
SLDataType StackTop(Stack* ptr);

//对栈进行判断,如果为空,返回true,否则返回false
bool StackEmpty(Stack* ptr);

//获取栈里面的元素个数
int StackSize(Stack* ptr);

void StackPop(Stack* ptr);

//栈的初始化
void StackInit(Stack* ptr)
{
	assert(ptr);
	ptr->a = NULL;
	ptr->capacity = ptr->top = 0;
}

//销毁栈
void StackDestroy(Stack* ptr)
{
	assert(ptr);
	free(ptr->a);
	ptr->a = NULL;
	ptr->capacity = ptr->top = 0;	//初始化时,top=0,表示指向栈顶的下一个元素
}

//在栈顶插入元素
void StackPush(Stack* ptr, SLDataType x)
{
	assert(ptr);
	if (ptr->top == ptr->capacity)
	{
		int newcapacity = ptr->capacity == 0 ? 4 : ptr->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ptr->a, newcapacity*sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ptr->a = tmp;
		ptr->capacity = newcapacity;
	}
	ptr->a[ptr->top++] = x;
}

//取栈顶元素
SLDataType StackTop(Stack* ptr)
{
	assert(ptr);
	assert(!StackEmpty(ptr));
	return ptr->a[ptr->top - 1];
}

//栈判空
bool StackEmpty(Stack* ptr)
{
	assert(ptr);
	return ptr->top == 0;
}

//销毁栈顶元素
void StackPop(Stack* ptr)
{
	assert(ptr);
	assert(!StackEmpty(ptr));

	ptr->top--;
}

//获取栈里面元素个数
int StackSize(Stack* ptr)
{
	assert(ptr);

	return ptr->top;
}

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

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

相关文章

微信小程序知识点归纳(一)

前言&#xff1a;适用于有一定基础的前端开发同学&#xff0c;完成从网页开发到小程序开发的知识转换。 先立框架&#xff0c;后砌墙壁 回顾&#xff1a;了解微信小程序开发流程-CSDN博客 初始页面结构&#xff0c;三部分pages、utils、配置&#xff0c;分别存放页面、工具类…

闪耀2023“物联之星”,迈威通信荣膺中国物联网企业创新产品榜

近日&#xff0c;IOTE 2024中国智联网生态大会暨“2023物联之星”年度榜单颁奖典礼在沪召开&#xff0c;迈威通信凭借其出色的技术创新和产品实力&#xff0c;其千兆卡轨式工业级5G路由器MIR785R成功荣登物联之星2023年度榜单——“中国物联网行业创新产品”。这不仅是对迈威通…

网络安全与IP地址的关联

网络安全与IP地址之间存在着密不可分的关系。IP地址作为网络通信的基础&#xff0c;对于网络安全的保障具有至关重要的作用。以下将详细探讨网络安全与IP地址之间的关联&#xff0c;以及IP地址在网络安全中的应用。 一、IP地址与网络安全的关系 IP地址是网络通信的基础&#x…

ISIS的基本配置

1.IS-IS协议的基本配置&#xff08;1&#xff09; 2.IS-IS协议的基本配置&#xff08;2&#xff09; 3.IS-IS协议的基本配置&#xff08;3&#xff09; 4.案例&#xff1a;IS-IS配置 R1的配置如下&#xff1a; [AR1czy]isis 1 [AR1czy-isis-1]is-level level-1 [AR1czy-isis-…

动手学深度学习17 使用和购买gpu

动手学深度学习16 Pytorch神经网络基础&#xff09; 5. GPUcolabNVIDIA GPUQA显存 5. GPU 课件&#xff1a; https://zh-v2.d2l.ai/chapter_deep-learning-computation/use-gpu.html 有GPU装cuda。 把模型参数放到指定设备上。 # 5.6. GPU # !nvidia-smi # 在命令行中&…

无限视差滚动(轮播)

无限视差滚动 无限视差滚动(轮播&#xff09;可以给用户一种无限滚动的感觉&#xff0c;视觉效果非常的好。话不多说&#xff0c;先来看效果 这边因为得控制GIF图片大小在5MB以内&#xff0c;导致看着不太丝滑 这种效果在国外用得很多&#xff0c;不过最近几年国内也慢慢开始使…

融合Transformer与CNN,实现各任务性能巅峰,可训练参数减少80%

论文er看过来&#xff0c;今天给各位推荐一个热门创新方向&#xff1a;CNNTransformer。 众所周知&#xff0c;CNN通过多层卷积自动学习空间层级特征&#xff0c;能够有效提取图像局部特征。而Transformer通过自注意力机制全局建模&#xff0c;能够有效处理长距离依赖关系。 …

鸿蒙OpenHarmony南向:【Hi3516标准系统入门(IDE方式)】

Hi3516标准系统入门&#xff08;IDE方式&#xff09; 注意&#xff1a; 从3.2版本起&#xff0c;标准系统不再针对Hi3516DV300进行适配验证&#xff0c;建议您使用RK3568进行标准系统的设备开发。 如您仍然需要使用Hi3516DV300进行标准系统相关开发操作&#xff0c;则可能会出现…

静态分析-RIPS-源码解析记录-01

token流扫描重构部分&#xff0c;这一部分主要利用php的token解析api解析出来的token流&#xff0c;对其中的特定token进行删除、替换、对于特定的语法结构进行重构&#xff0c;保持php语法结构上的一致性 解析主要在lib/scanner.php中通过Tokenizer这个类来实现,也就是在main…

视频号小店做店的最新最全攻略,小白也能快速上手轻松变现!

大家好&#xff0c;我是电商花花。 从开始接触视频号小店到现在已经两年多时间了&#xff0c;关于视频号小店也有不少经验和感触。 最近越来越多的人开始进入视频号小店的电商赛道&#xff0c;有人日均销售额做到几万甚至十几万。 想在视频号上变现赚钱&#xff0c;但是苦于…

APP广告转化流程对广告变现收益有影响吗?

对接广告平台做广告变现的APP开发者都清楚&#xff0c;广告变现的价格、收益不是一成不变的&#xff0c;经常会遇到eCPM波动对广告收益产生较大影响。 导致APP收益产生波动的因素包括&#xff1a;用户质量、广告类型、广告平台的资源波动、广告预算的季节性、广告展示量级等。…

R语言数据探索与分析-中国GDP回归分析与预测

首先读取数据&#xff1a; 将GDP列转换为常规数字格式 # 可视化GDP数据 # 查看数据结构 # 确保数据类型是正确的 第一张图片展示了中国2002年到2021年间的GDP增长趋势&#xff0c;这是一个时间序列图&#xff0c;其中横轴表示年份&#xff0c;纵轴表示GDP&#xff08;单位未…

springcloud alibaba微服务框架涉及的技术

一、微服务架构中核心模块及其使用技术总览 二、各模块详细说明 1、注册中心 该模块主要功能为 自动提供服务的注册与发现&#xff0c;集中式管理服务&#xff0c;让 服务调用端发现服务&#xff0c;让服务提供端注册服务&#xff0c;倘若没有注册中心&#xff0c;那客户端就…

Acwing2024蓝桥杯FloodFill

AcWing 687. 扫雷 模拟以下样例(10X10): 把扫雷地图转变为数字记录的地图:地雷记作-1,其余表示8个方向有几个地雷,完成后如下图: 接着搜索所有0联通块(为红色矩形),并且把联通块附近不是地雷的点(红色圆形)全标记为-1,如下图: 而答案就是当前该图中大于0的数的数目之和,再加上…

GPT-ArcGIS数据处理、空间分析、可视化及多案例综合应用教程

原文链接&#xff1a;GPT-ArcGIS数据处理、空间分析、可视化及多案例综合应用教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247603080&idx1&sn3e0d7015a2a717c320ebea3a673388ee&chksmfa82126fcdf59b795c7e2cea575470d42480ab809b926be5f94633eac…

国产银河麒麟V10SP1系统下搭建TiDB数据库操作步骤图文

开发目的&#xff1a;在国产银河麒麟系统中搭建TiDB数据库运行环境。 开发工具&#xff1a;银河麒麟系统V10SP1TiDBMySql数据库8.0。 具体步骤&#xff1a; 1、在VmWare虚拟机中安装好国产银河麒麟V10Sp1操作系统。 2、打开终端命令&#xff0c;安装TiDB相关软件&#xff1…

张驰咨询:AI与六西格玛——携手共进,非彼此替代

在历史的洪流中&#xff0c;技术与方法的演进如同波澜壮阔的画卷&#xff0c;不断书写着人类文明的篇章。六西格玛&#xff0c;作为一种追求极致品质与效率的方法论&#xff0c;是现代工业文明中的瑰宝。而当我们面对AI&#xff08;人工智能&#xff09;这一新时代的产物时&…

安卓模拟器Frida环境搭建 (mumu+adb+frida)

安卓模拟器Frida环境搭建 &#xff08;mumuadbfrida&#xff09; mumu模拟器安装adb与frida下载mumuadbfrida配置一般的报错实战 针对apk抓包问题&#xff0c;有的时候Android9已经不适用于现在的需求&#xff0c;需要更高的Android版本&#xff0c;mumu模拟器提供了Android12的…

【经验总结】Vue2中的全局变量(store

需求场景 需要在vue中存储一个可变的&#xff0c;可读写的全局变量在不同的js、页面中均可调用和读写 技术&#xff1a;使用vue的store 用法总结 一、定义变量 1、找到vue的/src/store路径&#xff0c;在modules文件夹下创建文件&#xff08;这里便于测试创建demo.js&…

Linux下安装JDK并配置环境变量

一、Oracle官网下载jdk 1、官网地址 https://www.oracle.com/java/technologies/downloads/#java17 2、命令下载 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 3、解压 tar -zxvf jdk-17_linux-x64_bin.tar.gz 4、配置环境变量 ec…