【数据结构】栈(Stack)和队列(Queue)

文章目录

    • 一、栈的概念及结构
    • 二、栈的特点
    • 三、栈的实现
      • 1.初始化栈
      • 2.判断栈空
      • 3.入栈
      • 4.出栈
      • 5.取栈顶元素
      • 6.栈的元素个数
      • 7.销毁
  • 队列
    • 一、队列的概念及结构
    • 二、队列的特点
    • 三、队列的实现
      • 1.初始化
      • 2.入队
      • 3.出队
      • 4.判断队空
      • 5.取队头元素
      • 6.取队尾元素
  • 总结

一、栈的概念及结构

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

在这里插入图片描述

栈顶:允许进行插入、删除操作的一端称为栈的栈顶(top),也称为表尾。
栈底:固定不动的一端,称为栈底(bottom),也称为表头。
进栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈/弹栈,出数据也在栈顶。

也分为顺序栈链栈(类比顺序表和链表)采用顺序存储的栈称为顺序栈,用一段物理地址连续的存储单元依次存储数据元素,通常以数组的形式实现;采用链式存储的栈称为链栈。

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些,因为数组尾插尾删的效率更高。

二、栈的特点

1.只能在栈顶进行插入和删除元素。
2.遵循后进先出原则,后入栈的元素先出栈,即最后插入的元素最先删除。
3.只能访问栈顶元素,不能从栈底或者中间访问元素。

三、栈的实现

栈的基本操作有:入栈(Push)、出栈(Pop)、取栈顶元素(Top)和判断栈是否为空(IsEmpty)等。

和顺序表一样,顺序栈采用动态存储的方式,根据需要来动态地申请空间。

队列的定义

#define INIT_SZ 10  //初始空间大小
#define INC_SZ 4	//每次扩容的空间大小
typedef int STDataType;//方便改存储的数据类型,下面以int示例
typedef struct Stack
{int* a;int top;//栈顶索引int capacity;//分配的空间容量
}ST;

1.初始化栈

//初始化
void STInit(ST* ps)
{assert(ps);//提高代码健壮性ps->a = (STDataType*)malloc(sizeof(STDataType) * INIT_SZ);if (NULL == ps->a){perror("malloc");return;}ps->capacity = INIT_SZ;//ps->top = -1;//top是栈顶元素的位置ps->top = 0;//top是栈顶元素的下一个位置
}

注意:栈顶下标top在初始化时,可以选择初始化为-1,表示栈顶元素的位置;也可以选择初始化为0,表示栈顶元素的下一个位置。top初始化的值会导致后面的基本操作写法有一点不同,随机选择一种即可。

2.判断栈空

判空条件与初始化时top的值有关。

//判断栈空
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;//初始化的值
}

3.入栈

//入栈
void STPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity)//栈内元素个数等于空间容量,需要进行扩容{STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * (INC_SZ + ps->capacity));if (NULL == tmp){perror("malloc");return;}ps->a = tmp;ps->capacity += INC_SZ;}//ps->a[++ps->top] = x;//ps->top初始化为-1时的写法ps->a[ps->top++] = x;
}

注意:栈顶下标top初始化为-1,表示栈顶元素的位置,每次入栈先++top,到下一个元素的位置,再插入;top如果初始化为0,表示栈顶元素的下一个位置,每次先插入,再++top。

4.出栈

//出栈
void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));//栈非空才能出栈ps->top--;
}

注意:删除的空间不能free掉,因为动态开辟的空间不能局部释放。

5.取栈顶元素

//返回栈顶元素
STDataType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));//要保证栈非空才能取栈顶元素//return ps->a[ps->top];//top初始化为-1时的写法return ps->a[ps->top - 1];
}

这里也会受到前面top初始化值的影响。

6.栈的元素个数

//栈的元素个数
int STSize(ST* ps)
{assert(ps);//return ps->top+1;//top初始化为-1时的写法return ps->top;
}

7.销毁

//销毁
void STDestroy(ST* ps)
{assert(ps);ps->a = NULL;free(ps->a);ps->top = 0 = ps->capacity = 0;
}

队列

一、队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的特点。
在这里插入图片描述就像人们排队一样,讲究先来后到,先排队的人享受完服务,先离开。

队头:进行删除操作的一端。
队尾:进行插入操作的一端。
入队列:队列的插入操作,入数据在队尾。
出队列:队列的删除操作,出数据在队头。

队列也可以用数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列是数组头删,效率会比较低。

队列也分为非循环队列循环队列,可以用数组或链表实现。下面主要介绍用链表实现的普通的非循环队列。

二、队列的特点

1.只能在队头删除数据,只能在队尾插入数据。
2.遵循先进先出原则,先入队的元素先出队,即先插入的元素先删除。
3.只能访问队头和队尾元素,不能从中间访问元素。

三、队列的实现

队列的基本操作有:入队(Push)、出队(Pop)、判断队列空(IsEmpty)取队头元素(Front)、取队尾元素(Back)等。

队列的定义
队列的链式存储结构是一个带有队头指针和队尾指针的单链表。

typedef int QDataType;//数据类型
//结点
typedef struct QueueNode
{QDataType data;struct QueueNode* next;
}QNode;
//队列
typedef struct Queue
{QNode* head;//队头指针QNode* tail;//队尾指针
}Queue;

1.初始化

不带头结点的链式队列的初始化。

void QueueInit(Queue* pq)
{assert(pq);pq->head = pq->tail = NULL;
}

2.入队

在这里插入图片描述入队相当于链表的尾插,只不过链表没有尾指针,需要从头结点开始遍历到尾结点,而队列可以通过队尾指针直接访问尾结点,效率更高。

void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newNode = (QNode*)malloc(sizeof(QNode));//申请结点if (NULL == newNode){perror("malloc");return;}newNode->data = x;newNode->next = NULL;if (NULL == pq->head)//空队列,第一次入队{pq->head = pq->tail = newNode;}else{pq->tail->next = newNode;//队尾的下个结点指向新结点pq->tail = newNode;//更新队尾指针}
}

3.出队

在这里插入图片描述出队相当于链表的头删。

void QueuePop(Queue* pq)
{assert(pq);assert(pq->head);QNode* head = pq->head;//保存头结点,释放空间pq->head = head->next;//更新队头指针free(head);//释放头结点的空间head = NULL;//防止野指针
}

注意:删除时要释放结点空间,必须先保存头结点,否则更新队头指针后无法找到该结点从而导致无法释放这块空间。

4.判断队空

队列为空的条件与初始化有关。

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;//或者return pq->tail == NULL;
}

5.取队头元素

QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));//队列非空是前提return pq->head->data;
}

6.取队尾元素

QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));//队列非空是前提return pq->tail->data;
}

总结

栈和队列都是一种特殊的线性表。

  • 栈的特点:后进先出,只能在表尾进行插入和删除。
  • 队列的特点:先进先出,只能在表头删除,在表尾插入。

  • 它们都可以用顺序存储和链式存储的方式。

    栈常用顺序存储结构即数组的方式,因为数组的尾插尾删效率高,但可能会存在频繁开辟内存空间和内存空间浪费的问题。而栈的链式存储结构,解决了空间浪费的问题,但每个节点都存放一个指针域,也会存在一定的内存开销,并且在每次申请和释放节点的过程中也存在一定的时间开销。

    队列常用链式存储结构即链表的方式,比链表多定义一个尾指针,解决尾插效率低的问题,并且不存在空间浪费。 而队列的顺序存储结构,由于插入需要挪动数据,效率低下,但循环队列可以解决这个问题,时间复杂度从O(N)变成了O(1),但仍存在内存空间浪费的问题。

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

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

相关文章

HR招聘面试测评,如何判断候选人的创新能力?

创新能力代表着一个人的未来发展潜力,创新能力突出的人,未来的上限就可能更高。而对于一个公司而言,一个具有创新能力的员工,会给公司带来新方案,新思路,对公司的长远发展拥有着十分积极的作用。 而在挑选…

Spark云计算平台Databricks使用,SQL

创建workspace:Spark云计算平台Databricks使用,创建workspace和Compute计算集群(Spark集群)-CSDN博客 1 创建schema 选择Calalog,点击Create schema 输入名字,Storage location选择workspace,数…

2024年小沙弥小视频,轻松吸引中老年观众,上手简单,轻松月入了万

利用人工智能工具制作小沙弥主题的抖音内容,已成为网络赚钱的新途径。这个项目主要吸引中老年人群体,尤其是对智慧和人生哲理感兴趣的观众。小沙弥以其温馨且启发性的内容,引起中老年用户的共鸣,为他们提供心灵慰藉。 项 目 地 …

AI工具摸索-关于写作(1)

虽然人工智能工具非常多,但是如果想要成为生产力,能达标的工具仍然非常少,除了最常用的chatgpt,其他的工具真的能达标吗,这篇文章主要就是对比市面上的一些工具, 但我这个人非常执拗,我认为作为生产力工具的功能必然是可以真正帮助我们的,而不是说作为一个写作工具结…

【Python时序预测系列】一文搞明白时序数据输入到LSTM模型的格式(案例解读)

这是我的第276篇原创文章。 一、引言 前面我介绍了多个方法实现单变量和多变量时序数据的单站点单步预测,好多小伙伴最近问我这个LSTM模型数据的输入的格式是怎么样的,今天我专门写一篇文章来聊一聊这个问题,希望对大家有所启发和帮助。 二、…

PyQt6--Python桌面开发(3.运行QTDesigner生成的ui文件程序)

运行QTDesigner生成的ui文件程序 用QTDesigner设计一个简单的UI 保存ui文件,放到项目里面去 通过pyqt6包里面的uic来加载ui文件 import sysfrom PyQt6.QtWidgets import QApplication from PyQt6 import uicif __name__ __main__:appQApplication(sys.argv)uiui…

Docker 安装的MySQL迁移数据库

1. 导出数据库 docker ps :查看数据库对应的 CONTAINER ID docker exec -it id /bin/bash : 进入到mysql的docker实例中 cd /usr/bin : 进入到bin目录 mysqldump -u root -p123456 study > /root/study_backup0509.sql :使用mysqldump备份库,注意密码与-p之间…

《探索信息技术中心一体化系统架构:提升企业数字化转型的效率与能力》

在当今数字化时代,信息技术中心(IT Center)扮演着至关重要的角色,它不仅是企业的技术支撑,更是推动数字化转型的引擎。为了更好地应对日益复杂的业务需求和技术挑战,许多企业开始探索一体化系统架构&#x…

一对一WebRTC视频通话系列(五)——综合调试和功能完善

本系列博客主要记录一对一WebRTC视频通话实现过程中的一些重点&#xff0c;代码全部进行了注释&#xff0c;便于理解WebRTC整体实现。 本专栏知识点是通过<零声教育>的音视频流媒体高级开发课程进行系统学习&#xff0c;梳理总结后写下文章&#xff0c;对音视频相关内容感…

数据分析处理的步骤是什么?制造业企业如何挑选数据分析处理软件?看这篇就够了

随着工业4.0的深入实施以及国家对制造业高质量发展战略的日益强调&#xff0c;工业数据已经崭露头角&#xff0c;成为生产经营活动中至关重要的核心要素。不仅如此&#xff0c;工业数据还作为优质的生产要素&#xff0c;为新兴生产力的形成提供了强有力的支撑&#xff0c;从而推…

服务异步通讯MQ

同步调用存在的问题: 异步调用方案: RabbitMQ安装: 第一种:在线拉取 docker pull rabbitmq:3-management 第二种:将已有的安装包放入再用load加载 我这里放到tmp包里边 然后:cd /tmp docker load -i mq.tar 加载进去 然后运行mq容器 docker run \-e RABBITMQ_DEFAULT_USER…

大模型入门(六)—— RLHF微调大模型

一、RLHF微调三阶段 参考&#xff1a;https://huggingface.co/blog/rlhf 1&#xff09;使用监督数据微调语言模型&#xff0c;和fine-tuning一致。 2&#xff09;训练奖励模型 奖励模型是输入一个文本序列&#xff0c;模型给出符合人类偏好的奖励数值&#xff0c;这个奖励数值…

未来编码探索:揭秘Java的进化之旅与技术革新!

Java是一种广泛使用的编程语言&#xff0c;自1995年问世以来&#xff0c;它在企业级应用、移动应用开发、大数据处理等领域都有着广泛的应用。随着时间的推移&#xff0c;Java也在不断发展和进化&#xff0c;以满足不断变化的技术需求和市场趋势。本文将全面详细地探讨Java的未…

MyBatis(该篇足已)

目录 一.MyBatis是什么&#xff1f; 二.为什么学习MyBatis呢&#xff1f; 三.MyBatis的学习 3.1MyBatis的开发流程 3.2MyBatis项目 四.MyBatis的增删改操作 五.参数占位符 #{} 和 ${} 六.映射返回 七.映射失败 八.数据库连接池 九.动态SQL 9.1<if>标签 9.2&…

LeetCode63:不同路径Ⅱ

题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么从左上角…

5.07 Pneumonia Detection in Chest X-Rays using Neural Networks

肺炎诊断是一个耗时的过程&#xff0c;需要高技能的专业人员分析胸部X光片chest X-ray (CXR)&#xff0c;并通过临床病史、生命体征和实验室检查确认诊断。 它可以帮助医生确定肺部感染的程度和位置。呼吸道疾病在 X 光片上表现为一处膨胀的不透明区域。然而&#xff0c;由于不…

力扣HOT100 - 155. 最小栈

解题思路&#xff1a; 辅助栈 class MinStack {private Stack<Integer> stack;private Stack<Integer> min_stack;public MinStack() {stack new Stack<>();min_stack new Stack<>();}public void push(int val) {stack.push(val);if (min_stack.i…

LeetCode 404.左叶子之和

LeetCode 404.左叶子之和 1、题目 题目链接&#xff1a;404. 左叶子之和 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别…

SaToken框架实现在Rpc上下文的login处理逻辑

最近在工作中遇到一个需求&#xff0c;需要在项目A中实现一个rpc接口供其他项目调用&#xff0c;接口返回登录token&#xff0c;从而实现其他项目的用户能免密登录到项目A。 项目A是用了SaToken来做的鉴权&#xff0c;原本我的打算是直接在rpc中调用StpUtil.login()方法来实现登…

在Flask中使用Celery完成异步和定时任务(Flask、Celery、Redis)

编程目标 通过使用Flask和Celery&#xff0c;实现一个简单的Web应用程序&#xff0c;能够接收HTTP POST请求&#xff0c;并异步发送电子邮件。 说明 使用Flask创建一个简单的Web应用程序&#xff0c;包含一个HTTP POST路由&#xff0c;用于接收发送电子邮件的请求。使用Cele…