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

🎁个人主页:我们的五年

🔍系列专栏: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;
}

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

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

相关文章

【Debug日记】albumentations包安装失败解决方案

直接pip安装pip install albumentations 报错&#xff1a; ERROR: Command errored out with exit status 1:command: D:\anaconda3\envs\pytorch\python.exe D:\anaconda3\envs\pytorch\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py build_wheel C:\Users…

【编程题-错题集】连续子数组最大和(动态规划 - 线性 dp)

牛客对应题目链接&#xff1a;连续子数组最大和_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 简单线性 dp。 1、状态表示 dp[i] 表示&#xff1a;以 i 位置为结尾的所有子数组中&#xff0c;最大和是多少。 2、状态转移方程 dp[i] max(dp[i - 1] arr[i], arr[i]) 3、返回…

Sarcasm detection论文解析 |使用 BERT 进行中间任务迁移学习的刺检测

论文地址 论文地址&#xff1a;https://www.mdpi.com/2227-7390/10/5/844#/ github&#xff1a;edosavini/TransferBertSarcasm (github.com) 论文首页 笔记框架 使用 BERT 进行中间任务迁移学习的讽刺检测 &#x1f4c5;出版年份:2022 &#x1f4d6;出版期刊:Mathematics &…

[C/C++] -- 装饰器模式

装饰器模式是一种结构型设计模式&#xff0c;它允许在不改变原始对象的基础上动态地扩展其功能。这种模式通过将对象包装在装饰器类的对象中来实现&#xff0c;每个装饰器对象都包含一个原始对象&#xff0c;并可以在调用原始对象的方法之前或之后执行一些额外的操作。 装饰器…

炫龙电脑数据恢复方法有哪些?4个常用方法大放送

随着科技的不断发展&#xff0c;电脑已成为我们日常生活中不可或缺的一部分。然而&#xff0c;无论是由于操作失误、病毒感染、系统崩溃还是硬件故障&#xff0c;数据丢失都可能是每个电脑用户都可能面临的问题。对于使用炫龙电脑的用户来说&#xff0c;了解并掌握一些基本的数…

webassembly入门详解(C++)

一、环境配置 环境说明,操作系统为window操作系统。 1.1 下载和安装python 下载 需要python版本至少3.6版本 python下载地址:https://www.python.org/getit/ 安装 检测安装结果 win+R组合键->cmd->输入python->回车 1.2 下载和安装emsdk 下载 下载地址:https://gi…

这个Python库Streamlit,5分钟内搭建可视化WEB应用

在数据科学的世界里&#xff0c;将分析结果快速、直观地呈现给非技术背景的决策者&#xff0c;是一项重要的技能。而Streamlit&#xff0c;这个开源的Python库&#xff0c;正是为此而生。它允许数据科学家和工程师通过少量的代码&#xff0c;快速创建和分享数据应用。今天&…

OpenAI推出DALL·E 3识别器、媒体管理器

5月8日&#xff0c;OpenAI在官网宣布&#xff0c;将推出面向其文生图模型DALLE 3 的内容识别器&#xff0c;以及一个媒体管理器。 随着ChatGPT、DALLE 3等生成式AI产品被大量应用在实际业务中&#xff0c;人们越来越难分辨AI和人类创建内容的区别&#xff0c;这个识别器可以帮…

【Git】Git学习-15:分支简介和基本操作

学习视频链接&#xff1a;【GeekHour】一小时Git教程_哔哩哔哩_bilibili​编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 git bran…

pycharm code行太长显示波浪线取消

实际操作如下&#xff1a;个人比较合适的位置为160,180时有点多 效果&#xff1a;

Agent AI智能体:塑造未来社会的智慧力量

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f916; Agent AI智能体&#xff1a;塑造未来社会的智慧力量&#x1f3af; 引言&#x1f331; 智能体的未来角色预览&#x1f4bc; 行业革新者&#x1f31f; 创意合作者&#x1f6e1;️ 公共安全与环保&#x1f680; …

武汉星起航:亚马逊欧洲站:丰富商品与卓越服务铸就高客单价典范

亚马逊&#xff0c;作为全球最大的电商平台之一&#xff0c;其欧洲站在全球电商市场中占据着举足轻重的地位。其中&#xff0c;亚马逊欧洲站的人均客单价更是高居世界前列&#xff0c;这背后究竟隐藏着哪些原因呢&#xff1f; 首先&#xff0c;亚马逊具有丰富且高质量的商品品…

工业镜头助力锂电制造业精准检测

在电动汽车、电动轻型车、电动工具、消费电子和新型储能等行业大发展的背景下&#xff0c;锂电池综合优势与下游领域对电池大容量、高功率、使用寿命和环境保护日益提升的需求相契合&#xff0c;存在广阔的市场应用前景。受益于动力、消费和储能三大细分领域的快速发展&#xf…

Debug项目失败Run成功

一&#xff1a;问题 idea中启动服务&#xff0c;服务一直在启动中&#xff0c;最后超时启动失败 重新构建项目也是一样 二&#xff1a;个人分析 debug因为断点太多了项目起不起来&#xff0c;试一下run直接运行&#xff0c;项目可以快速启动 三&#xff1a;解决办法 在控制…

Liunx系统怎么设置免密登录?看这一篇!

远程口令爆破也是黑客常用的手段&#xff0c;有些人安全意识薄弱的会设置一些简单的密码&#xff0c;这样分分钟会被黑客爆破进去&#xff0c;一旦操作系统沦陷&#xff0c;里面的数据必将被黑客一览无余&#xff0c;使用免密登录可以有效降低密码被爆破的风险&#xff0c;具体…

docker 方式 elasticsearch 8.13 简单例子

安装 docker 虚拟机安装 elastic search 安装本地 # 创建 elastic 的网络 docker network create elastic # 用镜像的方式创建并启动容器 docker run -d --name es --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" -e "xpack.secur…

Android 终端查看CPU信息源码分析

代码如下&#xff1a; 终端获取信息&#xff08;左为H9&#xff0c;右为H5&#xff09; 觉得本文对您有用&#xff0c;麻烦点赞、关注、收藏&#xff0c;您的肯定是我创作的无限动力&#xff0c;谢谢&#xff01;&#xff01;&#xff01;

minio安装部署

MinIO 介绍 MinIO是一个对象存储解决方案&#xff0c;它提供了与Amazon Web Services S3兼容的API&#xff0c;并支持所有核心S3功能。 MinIO有能力在任何地方部署 - 公有云或私有云&#xff0c;裸金属基础设施&#xff0c;编排环境&#xff0c;以及边缘基础设施。 MinIO 安装…

Android内核之Binder读写通信:binder_ioctl_write_read用法实例(七十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Python专题:三、数字和运算(2)

目录 一、数学运算 二、赋值运算 一、数学运算 1、运算符号 加法 减法- 乘法* 除法/ 计算机中浮点数表示有精度限制&#xff0c;Python有限&#xff0c;所以近似取数 2、除法取整// Python2中 整数/整数 值为整数 Python3中 整数/整数 整数or浮点数 //计算除法对结果取…