数据结构——栈和队列(队列的定义、顺序队列以及链式队列的基本操作)

news2024/11/16 21:35:25

目录

队列(queue)的定义

顺序队——队列的顺序表示和实现

顺序队列(循环队列)的类型定义

顺序队列上溢问题的解决方法

​编辑

循环队列的基本操作

队列的基本操作——队列的初始化

队列的基本操作——求队列的长度

队列的基本操作——循环队列入队

队列的基本操作——循环队列出队

队列的基本操作——取队头元素

队列的基本操作——取队尾元素

链队——队列的链式表示和实现

链队列的类型定义

链队列的基本操作

链队列的基本操作——链队列初始化

链队列的基本操作——链队列销毁

链队列的基本操作——将元素e入队

链队列的基本操作——将元素e出队


队列(queue)的定义

顺序队——队列的顺序表示和实现

  • 队列和栈一样,也是限定只能在表的“端点”进行的线性表
  • 队列在插入的时候,只能在表尾进行插入,在删除的时候,只能在表头进行删除。(先进先出),表尾即队尾,表头即队头
  • 栈和队列是线性表的子集(是插入和删除位置受限的线性表)
  • 由于队列的操作具有先进先出的特性,使得队列成为程序设计中解决类似排队问题的有用工具。
  • 队列的逻辑结构与同线性表相同,仍为一对一关系。
  • 队列的存储结构有顺序队和链队,以循环顺序队列更常见。
  • 关键是掌握入队出队操作,具体实现依顺序队或链队的不同而不同。

顺序队列(循环队列)的类型定义

  • 队列的顺序表示——用一维数组base[MAXQSIZE]
#define MAXQSIZE 100 //最大队列长度
typedef struct
{
	QElemType* base; //初始化的动态分配存储空间
	int front; //头指针(队头元素的下标)
	int rear;  //尾指针(队尾元素的下标)
}SqQueue;
顺序队列上溢问题的解决方法

初始:front = rear = 0

入队:base[rear] = x;  rear++;

出队:x = base[front]; front++;

空队标志:front == rear

上面的假设存在什么问题呢?有下面的两种情况:

解决上溢出的方法

1、将队中元素依次向队头方向移动。

缺点:浪费时间,每移动一次,队中元素都要移动。

2、将队空间设想成一个循环的表,即分配给队列的m个存储单元可以循环使用,当rear为maxqsize时,若向量的开始端空着,又可以从头使用空着的空间。当front为maxqsize时,也是一样。

解决假上溢的方法——引入循环队列

base[0]接在base[MAXQSIZE-1]之后,若rear+1==M,则令rear = 0;

实现方法:利用%运算

插入元素

Q.base[Q.rear] = x;  //base为动态分配的一维数组
Q.rear = (Q.rear + 1) % MAXQSIZE;

删除元素

x = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;

将上述方法想象成循环队列,如下图:

如果这样操作的话就会出现新的问题,就是队空和队满的时候,front = rear 

那么如何解决这个问题呢,我们接下面往下分析:

解决方案:

1、另外设一个标志以区别队空、队满

2、另设一个变量,记录元素个数

3、少用一个元素空间循环队列解决队满时判断方法——少用一个元素空间

循环队列的基本操作

  • 队列的基本操作——队列的初始化
#define MAXQSIZE 100
typedef int QElemType;
Status InitQueue(SqQueue& Q) //C++中的引用操作,不是单纯的值拷贝,类似给变量取别名,还是同一块内存
{
	Q.base = new QElemType[MAXQSIZE]; //分配数组空间,利用C++关键字new实现
	//.base = malloc(MAXQSIZE*sizeof(QElemType)); //C语言实现
	if (!Q.base)exit(OVERFLOW);
	Q.front = Q.rear = 0;
	return OK;
}
  • 队列的基本操作——求队列的长度
int QueueLength(SqQueue Q)
{
    return ((Q.rear-Q.front+MQXQSIZE)%MAXQSIZE);
}
  • 队列的基本操作——循环队列入队
Status EnQueue(SqQueue& Q, QlemType e)
{
	if ((Q.rear + 1) % MAXQSIZE == Q.front)return ERROR;  //队满
	Q.base[Q.rear] = e;    //新元素加入队尾
	Q.rear = (Q.rear + 1) % MAXQSIZE;//队尾指针+1
	return OK;
}
  • 队列的基本操作——循环队列出队
Status EnQueue(SqQueue& Q, QlemType &e)
{
	if ((Q.rear = Q.front)return ERROR;  //队空
	e = Q.base[front];    //保存队头元素
	Q.front = (Q.front + 1) % MAXQSIZE;//队头指针+1
	return OK;
}
  • 队列的基本操作——取队头元素
SElemType GetHead(SqQueue Q)
{
	if(Q.front!=Q.rear) //队列不为空
		return Q.base[Q.front];//返回队头指针元素的值,队头指针不变
}
  • 队列的基本操作——取队尾元素

链队——队列的链式表示和实现

        若用户无法估计所用队列的长度,则宜采用链队列

链队列的类型定义

#define MAXQSIZE 100  //最大队列长度
typedef struct Qnode
{
	QElemType data;
	struct Qnode* next;
}QNode,*QueuePtr;  //一个是结点类型,一个是指向结点的指针

typedef struct
{
	QueuePtr front;//队头指针
	QueuePtr rear; //队尾指针
}LinkQueue; //链式队列

链队列的基本操作

  • 链队列的基本操作——链队列初始化
Status InitQueue(LinkQueue& Q)
{
	Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
	Q.front->next = NULL;
	return OK;
}
  • 链队列的基本操作——链队列销毁

Status DestroyQueue(LinkQueue& Q)
{
	while (Q.front) 
	{
		p = Q.front->next;//指针p指向头结点的下一结点
		free(Q.front);    //释放头结点
		Q.front = p;      //把指针指向的结点变为新的头结点
	}
}
  • 链队列的基本操作——将元素e入队
Status EnQueue(LinkQueue& Q, QElemType e) {
	p = (QueuePtr)malloc(sizeof(QNode));
	if (!p) exit(OVERFLOW);
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
	return OK;
}
  • 链队列的基本操作——将元素e出队
思路:
p=Q.front->next;  //暂存头结点的下一个,也就是第一结点
e=p->data;        //将要删除的队头的数据存下来
Q.front->next=p->next; //将头结点指向第二结点
delete p;   //释放要删除的元素的内存空间

代码实现:
Status DeQueue (LinkQueue &Q,QElemType &e)
{
    if(Q.front==Q.rear) return ERROR;
    p=Q.front->next;
    e=p->data;
    Q.front->next=p->next;
    if(Q.rear==p) Q.rear=Q.front;
    delete p;
    return OK;
}
  • 链队列的基本操作——求链队列的队头元素
Status GetHead (LinkQueue Q QElemType &e)
{
    if(Q.front==Q.rear) return ERROR;
    e=Q.front->next->data;
    return OK;
}

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

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

相关文章

[数据集][目标检测]岩石种类检测数据集VOC+YOLO格式4766张9类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):4766 标注数量(xml文件个数):4766 标注数量(txt文件个数):4766 标注…

CurrentHashMap的底层原理

CurrentHashMap在jdk1.8之前使用的是分段锁,在jdk1.8中使用"CAS和synchronized"来保证线程安全。 jdk1.8之前的底层实现 CurrentHashMap在jdk1.8之前,通过Segment段来实现线程安全。 Segment 段 ConcurrentHashMap 和 HashMap 思路是差不多…

TDengine 签约前晨汽车,解锁智能出行的无限潜力

在全球汽车产业转型升级的背景下,智能网联和新能源技术正迅速成为商用车行业的重要发展方向。随着市场对环保和智能化需求的日益增强,企业必须在技术创新和数据管理上不断突破,以满足客户对高效、安全和智能出行的期待。在这一背景下&#xf…

如何通过 PhantomJS 模拟用户行为抓取动态网页内容

引言 随着网页技术的不断进步,JavaScript 动态加载内容已成为网站设计的新常态,这对传统的静态网页抓取方法提出了挑战。为了应对这一挑战,PhantomJS 作为一个无头浏览器,能够模拟用户行为并执行 JavaScript,成为了获…

探索数据结构:初入算法之经典排序算法

🔑🔑博客主页:阿客不是客 🍓🍓系列专栏:渐入佳境之数据结构与算法 欢迎来到泊舟小课堂 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 一、插入排序 步骤: 从第一个元素开…

OpenAI 刚刚推出 o1 大模型!!突破LLM极限

北京时间 9 月 13 日午夜,OpenAI 正式发布了一系列全新的 AI 大模型,专门用于应对复杂问题。 这一新模型的出现代表了一个重要突破,其具备的复杂推理能力远远超过了以往用于科学、代码和数学等领域的通用模型,能够解决比之前更难的…

Python和R均方根误差平均绝对误差算法模型

🎯要点 回归模型误差评估指标归一化均方根误差生态状态指标神经网络成本误差计算气体排放气候算法模型 Python误差指标 均方根误差和平均绝对误差 均方根偏差或均方根误差是两个密切相关且经常使用的度量值之一,用于衡量真实值或预测值与观测值或估…

HarmonyOS开发实战( Beta5.0)骨架屏实现案例实践

鸿蒙HarmonyOS开发往期必看: HarmonyOS NEXT应用开发性能实践总结 最新版!“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通) 介绍 本示例介绍通过骨架屏提升加载时用户体验的方法。骨架屏用…

无法加载用户配置文件怎么解决?

你有没有遇到过这种问题,蓝屏提示“User Profile Services服务登录失败。无法加载用户配置文件”。为什么会出现问题呢?可能的原因包括: 用户配置文件损坏:用户的配置文件可能已损坏,导致系统无法读取。 权限问题&…

linux更换阿里镜像源

第一步:进入 /etc/yum.repos.d目录下 cd /etc/yum.repos.d 第二步:编辑 CentOS-Base.repo 打开该文件 vi CentOS-Base.repo 第三步:点击键盘i,进入编辑模式 删除文件的全部内容:将阿里下面配置复制粘贴进取 [base] nam…

Ribbon (WPF)

Ribbon (WPF) 在本文中主要包含以下内容: Ribbon组件和功能应用程序菜单快速访问工具栏增强的工具提示 Ribbon是一个命令栏,它将应用程序的功能组织到应用程序窗口顶部的一系列选项卡中。Ribbon用户界面(UI)增加了特性和功能的可发现性,使用…

神经网络学习笔记——如何设计、实现并训练一个标准的前馈神经网络

1.从零设计并训练一个神经网络https://www.bilibili.com/video/BV134421U77t/?spm_id_from333.337.search-card.all.click&vd_source0b1f472915ac9cb9cdccb8658d6c2e69 一、如何设计、实现并训练一个标准的前馈神经网络,用于手写数字图像的分类,重…

如何制作Vector Vflash中加载的DLL文件--自动解锁刷写过程中27服务

案例背景: vFlash 是一种易于使用的工具,用于对一个或多个 ECU 进行刷写软件。由于方法灵活,它可以支持各种汽车原始设备制造商的不同刷写规范。它支持通过 CAN、CAN FD、FlexRay、LIN、以太网/DoIP 和以太网/SoAd 对 ECU 进行刷写。 vFlas…

SpringSecurity原理解析(六):SecurityConfigurer 解析

1、SecurityConfigurer SecurityConfigurer 在 Spring Security 中是一个非常重要的接口,观察HttpSecurity 中的很多 方法可以发现,SpringSecurity 中的每一个过滤器都是通过 xxxConfigurer 来进行配置的,而 这些 xxxConfigurer 其实都是 Sec…

针对Docker容器的可视化管理工具—DockerUI

目录 ⛳️推荐 前言 1. 安装部署DockerUI 2. 安装cpolar内网穿透 3. 配置DockerUI公网访问地址 4. 公网远程访问DockerUI 5. 固定DockerUI公网地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…

GBI(生成式商业智能)实际业务生产落地运用上的探索和实践

前言 最近在探索如何发展AI在业务上的驱动力时了解到了生成式商业智能这一概念,同时本人也在探索ChatBI这一技术的实际落地运用,其实二者几乎在实现效果层面是一个意思,GBI(Generative Business Intelligence)是偏向业务方面,而C…

[000-01-008].第05节:OpenFeign高级特性-超时控制

我的后端学习大纲 SpringCloud学习大纲 1.1.OpenFeign超时的情况: 在Spring Cloud微服务架构中,大部分公司都是利用OpenFeign进行服务间的调用,而比较简单的业务使用默认配置是不会有多大问题的,但是如果是业务比较复杂&#xff…

UiBot教程:实现复杂流程图的高效方法

在自动化测试和RPA(机器人流程自动化)领域,使用UiBot绘制复杂流程图是日常工作中常见的挑战之一。如何在繁杂的逻辑中保持高效?如何实现复杂流程的自动化设计而不迷失于其中?这是许多测试工程师和自动化开发者所面临的…

区块链之变:揭秘Web3对互联网的改变

传统游戏中,玩家的虚拟资产(如角色、装备)通常由游戏公司控制,玩家无法真正拥有这些资产或进行交易。而在区块链游戏中,虚拟资产通过去中心化技术记录在区块链上,玩家对其拥有完全的所有权,并能…

Loki 分布式日志中心服务

目录 Loki 是什么 Loki 配置文件介绍 Loki 安装 Promtail 配置文件介绍 Promtail 安装 Loki 整合 Grafana Loki 是什么 Loki 是一个专为日志聚合和查询设计的开源分布式日志管理系统,由 Grafana Labs 开发。它与 Prometheus 类似,但用于处理日志&a…