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

news2024/12/23 6:04:06

文章目录

    • 一、栈的概念及结构
    • 二、栈的特点
    • 三、栈的实现
      • 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.coloradmin.cn/o/1657667.html

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

相关文章

Python ValueError: bad transparency mask

修改前 修复后 运行正常 from PIL import Image# 读取图片 #报错信息解决ValueError: bad transparency mask--相关文档地址https://blog.csdn.net/kalath_aiur/article/details/103945309 #1. 检查 alpha 通道是否是一个有效的掩码。如果不是,则需要对 alpha 通道…

随机梯度下降SGD的理解和现象分析

提出问题:令人疑惑的损失值 在某次瞎炼丹的过程中,出现了如下令人疑惑的损失值变化图像: 嗯,看起来还挺工整,来看看前10轮打印的具体损失值变化: | epoch 1 | iter 5 / 10 | time 1[s] | loss 2.3137 |…

Hadoop3:HDFS的Shell操作(常用命令汇总)

一、简介 什么是HDFS的Shell操作? 很简单,就是在Linux的终端,通过命令来操作HDFS。 如果,你们学习过git、docker、k8s,应该会发现,这些命令的特点和shell命令非常相似 二、常用命令 1、准备工作相关命令…

【VTKExamples::Rendering】第一期 TestAmbientSpheres(环境照明系数)

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例TestAmbientShperes,介绍环境照明系数对Actor颜色的影响,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动…

Qt模型视图代理之QListView使用的简单介绍

往期回顾: Qt绘图与图形视图之Graphics View坐标系的简单介绍_graphics view 坐标系-CSDN博客 Qt模型视图代理之MVD(模型-视图-代理)概念的简单介绍-CSDN博客 Qt模型视图代理之QTableView应用的简单介绍-CSDN博客 Qt模型视图代理之QListView使用的简单介绍 一、最…

视频监控平台:交通运输标准JTT808设备SDK接入源代码函数分享

目录 一、JT/T 808标准简介 (一)概述 (二)协议特点 1、通信方式 2、鉴权机制 3、消息分类 (三)协议主要内容 1、位置信息 2、报警信息 3、车辆控制 4、数据转发 二、代码和解释 (一…

电商核心技术揭秘53:社群营销的策略与实施

相关系列文章 电商技术揭秘相关系列文章合集(1) 电商技术揭秘相关系列文章合集(2) 电商技术揭秘相关系列文章合集(3) 电商技术揭秘四十一:电商平台的营销系统浅析 电商技术揭秘四十二&#…

手机传输助手有哪些?如何快速互传文件?

手机已经成为我们生活和工作中不可或缺的一部分,而手机传输助手,作为一种帮助我们在不同设备之间快速、方便地共享文件的工具,其重要性不言而喻。无论是在工作中需要将文件从电脑传输到手机,还是在生活中想要与朋友分享美好的瞬间…

【智能算法】人工原生动物优化算法(APO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.获取代码 1.背景 2024年,X Wang受到自然界原生动物启发,提出了人工原生动物优化算法( Artificial Protozoa Optimizer, APO)。 2.算法原理 2.1算法思想 AP…

一文玩转Vue3参数传递——全栈开发之路--前端篇(8)

全栈开发一条龙——前端篇 第一篇:框架确定、ide设置与项目创建 第二篇:介绍项目文件意义、组件结构与导入以及setup的引入。 第三篇:setup语法,设置响应式数据。 第四篇:数据绑定、计算属性和watch监视 第五篇 : 组件…

导弹追踪效果实现_unity基础开发教程

Unity开发中导弹追踪的原理与实现 前言原理逻辑实现导弹逻辑目标赋值 应用效果结语 前言 ⭕在之前的一个项目的开发中,需要加入一个导弹追踪的游戏功能,且还要实现不规则发射路径,但是这种功能是第一次做,经过查阅资料和询问做过的…

java io包

InputStream InputStream 是 Java I/O 中所有输入流的抽象基类,它定义了读取字节流的基本方法。InputStream 类提供了许多子类,用于从不同的数据源读取数据,如文件、网络连接、内存等。 InputStream 提供了以下常用的方法: int…

Magic Studio Eraser API使用教程

AI橡皮擦 - 使用网址 Magic Studio的AI橡皮擦功能非常好用,能去除图片中的杂物。但是网页版只支持低分辨率下载,想要原图就得开会员,价格不菲。 不过官网其实提供了API接入方式,并且有100次的免费试用机会 API接入网站 在这里可…

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…

C++对象引用作为函数参数

使用对象引用作为函数参数最常见,它不但有指针作为参数的优点,而且比指针作为参数更简单、更方便。 引用方式进行参数传递,形参对象就是实参对象的“别名”,对形参的操作其实就是对实参的操作。 例如:用对象引用进行参数传…

基于Springboot的校园悬赏任务平台(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的校园悬赏任务平台(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构…

1010: 折半查找的实现

解法&#xff1a; #include<iostream> #include<vector> using namespace std; void solve() {int n;cin >> n;vector<int> vec(n);for (int& x : vec) cin >> x;int x;cin >> x;int l 0, r n-1, cnt 0;while (l < r) {cnt;int…

Python语言在地球科学交叉领域中的实践技术融合应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;Python能够运行在Linux、Windows、Macintosh、AIX操作系统上及不同平台&#xff08;x86和arm&#xff09;&#xff0c;Python简洁的语法和对动态输入的支持&#xff0c;再加上解释性语言的本质&…

代码随想录算法训练营第四十二天| 01背包问题(二维、一维)、416.分割等和子集

系列文章目录 目录 系列文章目录动态规划&#xff1a;01背包理论基础①二维数组②一维数组&#xff08;滚动数组&#xff09; 416. 分割等和子集①回溯法&#xff08;超时&#xff09;②动态规划&#xff08;01背包&#xff09;未剪枝版剪枝版 动态规划&#xff1a;01背包理论基…

【MySQL基本查询(上)】

文章目录 一、多行插入 指定列插入数据更新表中某个数据的信息&#xff08;on duplicate&#xff09;了解affected报告信息 二、检索功能1.select 查询1.1全列查询1.2指定列查询1.3where条件筛选子句案例 2.结果排序案例 3.筛选分页结果offset实现分页 一、多行插入 指定列插…