【数据结构】--- 探索栈和队列的奥秘

在这里插入图片描述
关注小庄 顿顿解馋૮(˶ᵔ ᵕ ᵔ˶)ა
💡个人主页:9ilk
💡专栏:数据结构之旅


上回我们学习了顺序表和链表,今天博主来讲解两个新的数据结构 — 栈和队列 , 请放心食用

文章目录

  • 🏠 栈
    • 📒 何为栈
      • 👿 栈后进先出是相对的
    • 📒 栈的实现
  • 🏠 队列
    • 📒 何为队列
    • 📒 队列的实现

🏠 栈

在这里插入图片描述

对于这么坨书,我们要拿到最下面的书是不是要最后才能拿到;而对于最上面的书它是最晚放上去的却能最先拿到,这样的一个场景就跟我们接下来要介绍的栈类似 — Last in First out(后进先出)

📒 何为栈

在这里插入图片描述

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

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

👿 栈后进先出是相对的

在这里插入图片描述
由图中我们可知,栈的后进先出是对于同时在栈里的数据而言的

📒 栈的实现

通过前面的分析我们知道,我们需要一个栈顶来表示数据,这跟我们链表的头结点有点相似,但是对于单链表来说实现栈,尾部插入数据并不方便,因此我们选择数组实现栈
在这里插入图片描述

  • 动态栈
typedef int Datatype;
typedef struct Stack
{
	Datatype* arr;
	int top;
	int capacity;
}ST;
  • 栈的初始化与销毁
//初始化
void StackInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

关于top的初始化:1.top表示栈顶元素的下一个位置时,让top初始化为0,插入数据时先top后++ ;2.top表示栈顶元素 时,top初始化为-1,此时先++后再用top

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

  • 栈的插入数据和删除数据
    这里有了前面顺序表的基础就很简单了,不过要注意压栈和出栈都是在栈顶
//入栈
void StackPush(ST* ps, Datatype data)
{
	assert(ps);
	if (ps->capacity == ps->top)
	{//扩容
		int newcapacity = 0;
		newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		Datatype* temp = (Datatype*)malloc(newcapacity * sizeof(Datatype));
		if (temp == NULL)
		{
			perror("malloc failed");
			return;
		}
		ps->arr = temp;
		ps->capacity = newcapacity;
	}
	//入栈
	ps->arr[ps->top++] = data;

}
//出栈
void StackPop(ST* ps)
{
	assert(ps);
	//栈不能为空
	assert(ps->top != 0);
	ps->top--;
}
  • 获取栈顶元素
// 获取栈顶元素 
Datatype StackTop(ST* ps)
{
	assert(ps);
	//栈不能为空
	assert(ps->top != 0);
	return ps->arr[ps->top - 1];
}
  • 判断是否为空
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0 ? 1 : 0;

}
  • 获取栈中有效数据个数
// 获取栈中有效元素个数 
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

🏠 队列

栈是后进先出,那有我们的先进先出(First in First out)吗 ? 当然有,跟现实中我们排队买票一样,这样数据结构叫做队列

📒 何为队列

在这里插入图片描述

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

📒 队列的实现

由于我们是先进先出,出在队头出,进在队尾进,所以我们需要两个“指针”front 和 rear 来标识位置有效率些。

那用数组来实现好还是链表呢?
在这里插入图片描述
用数组的话不好出数据,所以我们这里推荐用链表实现;同时我们可以将front和rear封装进一个结构体这样比较省事

  • 队列结构
typedef int Datatype;
typedef struct QNode
{
	Datatype data;
	struct QNode* next;
}QNode;


typedef struct Quque
{
	QNode* head;
	QNode* tail;
	int size;
}Quque;

注:我们可以定义一个size表示数据个数,弥补链表需要循环遍历确定数据个数的缺陷

  • 队列的初始化和销毁
//队列的初始化和摧毁
void QuqueInit(Quque* pq)
{
	assert(pq);
	pq->size = 0;
	pq->head = pq->tail = NULL;
}
void QuqueDestroy(Quque* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;

}
  • 入队和出队

出队就是链表的头删 入队就是尾插

//队列的入队列和出队列
void QuquePop(Quque* pq)
{
	assert(pq);
	assert(pq->head != NULL);//对嘞不能为空
	//0个结点

	//1个结点
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
	pq->size--;
}
void QuquePush(Quque* pq, Datatype x)
{
	assert(pq);
	//申请新结点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc failed");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->head == NULL)
	{//0个结点
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}
  • 获取头元素和尾元素
//队列的头元素和尾巴元素
Datatype QuqueFront(Quque* pq)
{
	assert(pq);
	assert(pq->head != NULL);
	return pq->head->data;//设置两个指针进结构体的好处
}
Datatype QuqueBack(Quque* pq)
{
	assert(pq);
	assert(pq->head != NULL);
	return pq->tail->data;//设置两个指针进结构体的好处
}
  • 队列是否为空
//队列是否为空
bool QuqueEmpty(Quque* pq)
{
	assert(pq);
	if (pq->size == 0)
	{
		return true;
	}
	else
	{
		return false;
	}

}
  • 队列有效数据个数
//队列数据个数
int QuqueSize(Quque* pq)
{
	assert(pq);
	return pq->size;

}

本次分享到这就结束咯,下次我们将讲解链表,栈和队列的OJ题,敬请期待 ~

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

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

相关文章

红黑树内部结点数量分析

红黑树内部结点数量分析 一、红黑树的性质二、黑高与内部结点数量2.1最大内部结点数量2.2最小内部结点数量 三、伪代码实现四、C语言代码实现五、结论 红黑树是一种自平衡的二叉搜索树,它通过一系列复杂的性质和操作来维持平衡,从而确保各种动态集合操作…

来get属于你的达坦科技令人心动的offer吧!

我们是谁 达坦科技始终致力于打造高性能Al Cloud 基础设施平台DatenLord,积极推动AI应用的落地。DatenLord通过软硬件深度融合的方式,提供高性能存储和高性能网络。为AI 应用提供弹性、便利、经济的基础设施服务,以此满足不同行业客户对AICl…

【Unity每日一记】如何让Sprite精灵图集的背景图层变成透明,方便切割

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:uni…

CSS基础:4种简单选择器的详解

你好,我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生,2年时间从1800到月入过万,工作5年买房。 分享成长心得。 261篇原创内容-公众号 后台回复“前端工具”可获取开发工具,持续更新中 后台回复“前端基础…

Axure案例分享—垂直手风琴(附下载地址)

今天分享的案例是Axure8(兼容9和10)制作的垂直手风琴 一、功能介绍 折叠或展开多个面板内容,默认为展开一项内容,点击任一收起的选项,展开面板,其他面板收起二、制作过程 原型是由矩形组件以及动态面板构成, 拖入一…

面向C++程序员的Rust教程(二)

先序文章请看: 面向C程序员的Rust教程(一) 所有权与移动语义 要说Rust语言跟其他语言最大的区别,那笔者觉得非数这个所有权和移动语义莫属。 深浅复制 对于绝大多数语言来说,变量/对象之间的赋值通常都是复制语义。…

python标准数据类型--元组常用方法

在Python中,元组(Tuple)是一种不可变的有序集合,它与列表类似,但是元组中的元素不能被修改。元组通常用于存储不可变的数据集合,例如一组常量或者一组固定的值。本篇博客将介绍一些Python中元组的常用方法&…

软考高级架构师:人工智能芯片概念和例题

一、AI 讲解 人工智能芯片是专门设计来处理与人工智能(AI)相关的任务的集成电路。这些芯片针对AI应用的高计算需求进行了优化,以提升处理速度和效率,同时降低能耗。它们在AI领域,如深度学习、机器学习和数据分析中发挥…

python爬虫获取豆瓣前top250的标题(简单)

今天是简略的一篇,简单小实验 import requests from bs4 import BeautifulSoup# 模拟浏览器的构成(请求头) headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch…

10 款最佳 Mac 数据恢复软件,在为时已晚之前值得尝试

查看 10 年适用于 Mac 的 2024 款最佳免费数据恢复软件,可在大多数在线搜索中找到。精选列表将帮助您做出明智的决定并节省您的时间和精力。 10 款最佳 Mac 数据恢复软件 很明显,您此后将面临数据丢失事件。理所当然地,您期待一款可靠、与您…

中文大模型隐私保护哪家强?InternLM 与 Baichuan2 胜出!

引言:中文大模型隐私保护能力探索 本文研究了大语言模型(LLMs)对隐私和安全的影响,采用了三层渐进框架对语言系统的隐私进行评估。主要目标是全面评估LLMs对私人信息的敏感性,并检查其在识别、管理和保护敏感数据方面…

微信小程序短链接工具推荐

现在微信小程序大行其道,但工作中大部分人选择了短链接的方式来推广微信小程序,那么微信小程序短链接工具哪个好?今天就分享一篇从网上看到的关于《微信小程序短链接工具推荐》文,作者是souki,一起来看看吧! 一、缩链 1、生成方…

【智能算法】阿基米德优化算法(AOA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2020年,Hashim等人受到阿基米德定律启发,提出了阿基米德优化算法(Archimedes Optimization Algorithm,AOA)。 2.算法原理 2.1算法思想 …

python导入本地当前目录下的文件和父目录下的文件

今天我想要导入本地当前目录下的文件和父目录下的文件,网上查了很多教程,但还都是报错,最后几经尝试,终于成功解决了这一问题,在这里详细记录一下过程,同时也希望能够对大家有所帮助~~~:) 导入…

Python人工智能应用---中文分词词频统计

目录 1.中文分词 2.循环分别处理列表 (1)分析 (2)代码解决 3.词袋模型的构建 (1)分析需求 (2)处理分析 1.先实现字符串的连接 2.字符串放到新的列表里面 4.提取高频词语 &…

vivado 向 SVF 目标添加器件

向 SVF 目标添加器件 创建 SVF 目标后 , 可向其中添加器件以定义 SVF JTAG 器件链配置。 SVF JTAG 器件链配置应与目标硬件链相匹配 , 以 确保能正确执行 SVF 文件。 使用 Vivado IDE 单击“ ”按钮以向 SVF 链添加赛灵思器件或非赛灵思器件。…

程序·人生

诡异之极 2024.03.12 清新环境(股票代码002573)委托卖出 20000股,委托价4.58,当日最高价4.57 2024.03.11 清新环境(股票代码002573)委托卖出 20000股,委托价4.55,当日最高价4.54 …

【Python系列】读取 Excel 第一列数据并赋值到指定列

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

windwos安全加固

一、账号管理 按用户类型分配账号 目的:根据系统要求,设定不同账户和组,管理员、数据库 sa、审计用户、来宾用户等 实施方法: 打开本地用户和计算机管理器 ​ 1.打开运行,输入lusrmgr.msc 2.根据用户要求将账户加入…

鸡尾酒排序解读

在数据处理的海洋中,排序算法无疑是引领我们探索数据规律的灯塔。今天,我们要探讨的是一种有趣且独特的排序算法——鸡尾酒排序。鸡尾酒排序,也被称为定向冒泡排序、双冒泡排序或搅拌排序,是冒泡排序的一种变体,它通过…