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

news2024/11/18 10:46:54

在这里插入图片描述
关注小庄 顿顿解馋૮(˶ᵔ ᵕ ᵔ˶)ა
💡个人主页: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题,敬请期待 ~

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

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

相关文章

牛客 2024春招冲刺题单 ONT102 牛牛的果实排序【simpe 要知道如何判断是否是质数 Java,Go,PHP】

题目 题目链接: https://www.nowcoder.com/practice/975a263e2ae34a669354e0bd64db9e2a 核心 需要牢牢记住下面的代码//判断是否为质数public boolean isPrime(int n){if(n1) return false;if(n2 || n3) return true;if(n%6!1 && n%6!5) return false; /…

C++(语法以及易错点2)

1.内联函数 1.1 概念 以inline修饰的函数叫做内联函数,编译时C编译器会在调用内联函数的地方展开,没有函数调 用建立栈帧的开销,内联函数提升程序运行的效率。 ​int ADD(int a,int b) {return ab; }​ 1.2 特性 1. inline是一种以空间换时间…

spring security6重写登陆验证

spring security的认证流程 2. 从文档上可以看出来,UsernamePasswordAuthenticationFilter和AuthenticationManager是认证的关键步骤,/login传过来的username和password由UsernamePasswordAuthenticationFilter接收处理成UsernamePasswordAuthenticatio…

设计模式总结-组合模式

组合设计模式 模式动机模式定义模式结构组合模式实例与解析实例一:水果盘实例二:文件浏览 更复杂的组合总结 模式动机 对于树形结构,当容器对象(如文件夹)的某一个方法被调用时,将遍历整个树形结构&#x…

基于SSM的品牌银饰售卖平台(有报告)。Javaee项目。ssm项目。

演示视频: 基于SSM的品牌银饰售卖平台(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring …

LeetCode - 边积分最高的节点

2374. 边积分最高的节点 这是一个有向图,且每个节点都只有一条出边,指向0的边有1,2,3,4 10, 指向7的有5,6 11. 我们只需要一次遍历就可以解决,先搞一张哈希表,k存节点…

docker安装nacos,单例模式(standalone),使用内置的derby数据库,简易安装

文章目录 前言安装创建文件夹docker指令安装docker指令安装-瘦身版 制作docker-compose.yaml文件查看页面 前言 nacos作为主流的服务发现中心和配置中心,广泛应用于springcloud框架中,现在就让我们一起简易的部署一个单例模式的nacos,版本可…

Qt+OpenGL-part3

1-4EBO画矩形_哔哩哔哩_bilibili 可以绘制两个三角形来组成一个矩形&#xff08;OpenGL主要处理三角形&#xff09; 直接画两个三角形&#xff1a; #include "openglwidget.h" #include <QDebug>unsigned int VBO,VAO; unsigned int shaderProgram;//顶点着…

快排序解读

排序算法是计算机科学中不可或缺的一部分&#xff0c;它们在各种数据处理场景中发挥着关键作用。在众多排序算法中&#xff0c;快速排序以其高效的性能和简洁的实现成为了许多程序员的首选。今天&#xff0c;我们就来深入剖析快速排序算法&#xff0c;了解其原理、实现方式以及…

【【萌新的Pytorch入门之Python的学习】】

学习记录 - 参考记录来自B站up主 -爆肝杰哥 ① NumPy 包为 Python 加上了关键的数组变量类型&#xff0c;弥补了 Python 的不足&#xff1b; ② Pandas 包在 NumPy 数组的基础上添加了与 Excel 类似的行列标签&#xff1b; ③ Matplotlib 库借鉴 Matlab&#xff0c;帮 Python 具…

mysql 基本查询

学习了mysql函数&#xff0c;接下来学习mysql基本查询。 1&#xff0c;基本查询语句 MySQL从数据表中查询数据的基本语句为SELECT 语句。SELECT语句的基本格式是&#xff1a; SELECT (*I <字段列表>} FROM <表1>,<表2>..[WHERE<表达式> [GROUP BY <…

C++入门(以c为基础)——学习笔记2

1.引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间。在语法层面&#xff0c;我们认为它和它引用的变量共用同一块内存空间。 可以取多个别名&#xff0c;也可以给别名取别名。 b/c/d本质都是别名&#…

QA测试开发工程师面试题满分问答3: python的深拷贝和浅拷贝问题

在 Python 中&#xff0c;深拷贝&#xff08;deep copy&#xff09;和浅拷贝&#xff08;shallow copy&#xff09;是用于创建对象副本的两种不同方式。 浅拷贝是创建一个新的对象&#xff0c;该对象与原始对象的内容相同&#xff08;包括内部嵌套对象的引用&#xff09;&…

SSM框架学习——了解Spring与Eclipse创建Maven项目

了解Spring 什么是Spring Spirng是分层的JavaSE/EE全栈轻量级开源框架&#xff0c;以控制反转IoC和面向切面编程AOP为内核&#xff0c;使用基本的JavaBean来完成EJB的工作。 Spring框架采用分层架构&#xff0c;它的一些列功能被分为若干个模块。 上图中的红色背景模块为本…

提示工程概要

提示工程 1. 两大原则 原则 1&#xff1a;编写清晰具体的说明 使用分隔符 三引号&#xff1a;“”"三个反引号&#xff1a;三个破折号&#xff1a;—尖括号&#xff1a;<>XML标签&#xff1a; 要求结构化输出 HTMLJSONXMLPython字典 检查条件是否满足 检查执行…

C++ 类和对象(初篇)

类的引入 C语言中&#xff0c;结构体中只能定义变量&#xff0c;在C中&#xff0c;结构体内不仅可以定义变量&#xff0c;也可以定义函数。 而为了区分C和C我们将结构体重新命名成class去定义 类的定义 标准格式&#xff1a; class className {// 类体&#xff1a;由成员函…

linux安装和使用Rancher

linux安装和使用Rancher Rancher介绍请看如下博客 arm架构安装Rancher并导入k8s集群解决Error: no objects passed to apply 华为云arm架构安装k8s(kubernetes) linux下安装Rancher Rancher部署监控k8s集群状态等,比Dashboard插件强大 提前安装好K8S 在master上执行#如果…

学习心得1

这时我第一次更学习心得&#xff01;不足的在评论区指教。 首先先来分享一下&#xff0c;刷一维数组题目的方法。 仔细读题&#xff0c;不会做的题目先完成输入输出。不要干等着着急&#xff0c;就跳到下一题。如果使用的时oj&#xff0c;那就没有题解但是使用洛谷、LeetCood…

【热门话题】计算机视觉入门:探索数字世界中的“视觉智能”

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 计算机视觉入门&#xff1a;探索数字世界中的“视觉智能”摘要正文一、计算机视…

MATLAB——知识点备忘

最近在攻略ADC建模相关方面&#xff0c;由好多零碎的知识点&#xff0c;这里写个备忘录。 Matlab 判断一个数是否为整数 1. isinteger 函数 MATLAB中&#xff0c;可以使用 isinteger 函数来判断一个数是否为整数&#xff0c;例如&#xff1a;要判断x是否为整数可以采用以下代…