【数据结构】链式队列解析(C语言版)

数据结构——链队列解析过程和简单代码实现:
  • 一、简单概念:
    • 动图展示:
      • (1)入队:
      • (2)出队:
  • 二、顺序队列:
    • 思路
    • 步奏:
      • (1)入队操作:
      • (2)出队操作:
    • 简单实现代码:
  • 三、链式队列
    • (1)声明
    • (2)入队操作:
    • (3)出队操作:
    • (4)检查队列是否为空:
    • 全部代码:

一、简单概念:

队列,又称为伫列(queue),是先进先出(FIFO,First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作

队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加

与栈(stack)不同的是,队列是FIFO(First In First Out,先进先出),进入队列的一端叫尾部(rear),出队列的一端叫头部(front)。队列的主要操作也有两个:入队(offer)、出队(poll)

动图展示:

(1)入队:

在这里插入图片描述

从图中可以看到,A、B、C三个元素都是从队尾(rear)进入,就像现实生活中的排队,先来的就排在前面

(2)出队:

在这里插入图片描述

从图中可以看出,出队的顺序是A->B->C,也就是入队的顺序,即说明了队列是遵循FIFO的。队列的引用也十分广泛,锁的实现、生产者-消费者模型等都离不开队列

队列也有两种实现方式:顺序队列链式队列

二、顺序队列:

思路

在顺序队列中,通常让队尾指针rear指向刚进队的元素的位置,让队首指针 front 指向刚出队的元素的位置。因此,元素进队的时候rear指针要向后移动,元素出队的时候front指针也要向后移动。这样经过一系列的操作后,两个指针最终会到达数组的末端处,虽然队中已没有了元素,但是仍然无法插入元素,这就是所谓的“假溢出”。

为了解决假溢出的问题,可以将数组弄成一个环状,让 rear 和 front 指针沿着环走,这样就不会出现无法继续走下去的情况,这样就产生了循环队列,如下图所示 :

  • 队空状态 :qu.rear == qu.front

  • 队满状态 : (qu.rear + 1) % Maxsize == qu.front

  • 元素的进队操作 :qu.rear = (qu.rear + 1) % Maxsize ; qu.data[qu.rear] = x ;

  • 元素的出队操作 :qu.front = (qu.front + 1) % Maxsize ; x = qu.data[qu.front] ;

本次思路中 元素入队时先移动指针,后存入元素;元素出队时也是先移动指针,后元素出队

步奏:

(1)入队操作:
int inQueue(Squeue &qu,int x)
{//判断队列是否已满,若满则无法入队if((qu.rear + 1) % Maxsize == qu.front){return 0;}//队列没有满,则先移动指针,在插入元素qu.rear = (qu.rear + 1) % Maxsize;qu.data[qu.rear] = x;return 1; 
}
(2)出队操作:
int deQueue(Squeue &qu,int &x)
{//若队列已空,则无法取出元素if(qu.front == qu.rear){return 0;}//否则先移动指针,再将元素取出qu.front = (qu.front + 1) % Maxsize;x = qu.data[qu.front];return 1;
}

简单实现代码:

//顺序队列
#include <stdio.h>
#include <stdlib.h>
#define Maxsize 20//定义队列的结构体 
typedef struct Squeue{int data[Maxsize];int front;int rear;
}Squeue; //初始化队列 
void InitQueue(Squeue &qu)
{qu.front = qu.rear = 0;
}//判断队列是否为空 
int isQueueEmpty(Squeue qu)
{if(qu.front == qu.rear){return 1;}else{return 0;}
}//元素入队操作 
int inQueue(Squeue &qu,int x)
{//若队满则无法入队 if((qu.rear + 1) % Maxsize == qu.front){return 0;}qu.rear = (qu.rear + 1) % Maxsize;qu.data[qu.rear] = x;return 1; 
}//元素出队操作 
int deQueue(Squeue &qu,int &x)
{//若队空则无法出队 if(qu.front == qu.rear){return 0;}qu.front = (qu.front + 1) % Maxsize;x = qu.data[qu.front];return 1;
}int main()
{Squeue q;int i , n , x , a;InitQueue(q);scanf("%d",&n);for(i = 0;i < n;i++){scanf("%d",&a);inQueue(q,a);}//当队列非空时,输出队列中所有数据 while(!isQueueEmpty(q)){deQueue(q,x);printf("%d ",x);}return 0;
}

三、链式队列

以 模拟患者在医院等待就诊的情况为例子 实现链式队列:

  • 患者到达诊室,将病历交给护士,排到等待队列中候诊
  • 护士从等待队列中取出下一位患者的病历,该患者进入诊室就诊
  • 功能如下:

1)排队: 输入排队患者的病历号(随机产生),加入到就诊患者排队队列中
2)就诊: 患者队列中最前面的病人就诊,并将其从队列中删除
3)查看: 从队首到队尾列出所有排队患者的病历号
4)下班: 退出运行

(1)声明

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>typedef int ElementType;typedef struct Node{ElementType data;		//	存放数据 struct Node *next;		//	链表指针 }Node;typedef struct SeqQueue{Node *head;				//	队列头部 Node *wei; 				//	队列尾巴 ElementType size;		//	计算队列长度 
}Seq; typedef struct SeqQueue* Queue;		//	代表队列这个结构体指针

(2)入队操作:

//	创建链表,存放数据
Node *Create_Link(ElementType data)
{Node * new = (Node *)malloc(sizeof(Node));	//	开辟空间存数据 if(new == NULL){printf("开辟空间失败\n");}new ->data = data;			//	存放队列数据new ->next = NULL;			//	让尾巴指向NULLreturn new;					//	返回节点指针
}//	判断队列是否为空
bool QueueEmpty(Queue q) {if (q->head == NULL)return true;		//		队列为空return false;
}//	入队 
Queue * Push(Queue sum,ElementType data)	
{Node *LinkHead = Create_Link(data);		//	接收链表空间节点指针Queue p = sum;if(QueueEmpty(p) == true){p->head = p->wei= LinkHead;		//		第一次赋值会进入 return p;			//	返回值指向队列的头指针}else{p->wei->next = LinkHead;		//		让队尾next指针指向这个空间 p->wei = LinkHead;				//		队尾指针存入这个空间 }p->size++;				//		计算队伍长度 
}

(3)出队操作:

//	出队 
ElementType Pop(Queue q)
{ElementType count;		//	取队列数据 Node *Link;				if(QueueEmpty(q) == true){printf("数据已经从队列出完\n");q->wei = NULL;return -1;}Link = q->head;			//	让队列头给链表指针 count = Link->data;		//	链表头指针取出数据 q->head = Link->next;	//	让队列头指针移到链表头指针下一个节点位置,并指向它 free(Link);				//	释放已经出队的链表节点 return count;			//	返回取出的数据 
}

(4)检查队列是否为空:

//	判断队列是否为空
bool QueueEmpty(Queue q) {if (q->head == NULL)return true;		//		队列为空return false;
}

全部代码:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>typedef int ElementType;typedef struct Node{ElementType data;		//	存放数据 struct Node *next;		//	链表指针 }Node;typedef struct SeqQueue{Node *head;				//	队列头部 Node *wei; 				//	队列尾巴 ElementType size;		//	计算队列长度 
}Seq; typedef struct SeqQueue* Queue;//	初始化队列 
void Init_SeqQueue(Queue q)
{q->head = NULL;q->wei  = NULL;q->size = 0;	
}//	创建链表,存放数据
Node *Create_Link(ElementType data)
{Node * new = (Node *)malloc(sizeof(Node));	//	开辟空间存数据 if(new == NULL){printf("开辟空间失败\n");}new ->data = data;			//	存放队列数据new ->next = NULL;			//	让尾巴指向NULLreturn new;					//	返回节点指针
}//	判断队列是否为空
bool QueueEmpty(Queue q) {if (q->head == NULL)return true;		//		队列为空return false;
}//	入队 
Queue Push(Queue sum,ElementType data)	
{Node *LinkHead = Create_Link(data);		//	接收链表空间节点指针Queue p = sum;if(QueueEmpty(p) == true){p->head = p->wei= LinkHead;		//		第一次赋值会进入 return p;			//	返回值指向队列的头指针}else{p->wei->next = LinkHead;		//		让队尾next指针指向这个空间 p->wei = LinkHead;				//		队尾指针存入这个空间 }p->size++;				//		计算队伍长度 
}//	出队 
ElementType Pop(Queue q)
{ElementType count;		//	取队列数据 Node *Link;				if(QueueEmpty(q) == true){printf("数据已经从队列出完\n");q->wei = NULL;return -1;}Link = q->head;			//	让队列头给链表指针 count = Link->data;		//	链表头指针取出数据 q->head = Link->next;	//	让队列头指针移到链表头指针下一个节点位置,并指向它 free(Link);				//	释放已经出队的链表节点 return count;			//	返回取出的数据 
}//	初始化菜单 
void Init_Memu()
{printf("***********************************\n");printf("*          1.入队                 *\n");printf("*          2.出队                 *\n");printf("*          3.取队头元素           *\n");printf("*          4.查看队列是否为空     *\n");printf("*          5.插入队列(排队)       *\n");printf("*          6.就诊                 *\n");printf("*          7.查看                 *\n");printf("*          8.下班                 *\n");printf("***********************************\n");}//功能选择函数 
ElementType Choose_GN()
{int flag;scanf("%d",&flag);return flag;
}//	主函数 
int main()
{Seq S_Queue;			//	创建队列结构体对象 Init_SeqQueue(&S_Queue);	//	初始化队列 Queue q = NULL;			 int temp;int num=0;while(1){Init_Memu();printf("请选择你的需求:\n"); temp =  Choose_GN();Node* p = NULL;switch(temp){//	入队 case 1:{ElementType num;while(1){printf("请输入你要进队列的数据(输入0时结束输入):\n"); scanf("%d",&num);if( num == 0){break;}q = Push(&S_Queue,num);		//	接受队头指针head }}break;//	出队	case 2:{int flag;while(1){flag = Pop(&S_Queue);if(flag == -1){printf("出队列完毕\n");	break;}else{printf("出队数据为: %d\n",flag);}}}break;//	取队头元素	case 3:{ElementType sum;p = q->head;		//	取出队头指针 if( p == NULL){printf("队伍已经出队,没有数据\n");break;} sum = p->data;		//	队头指针取值 printf("队列头数据为: %d \n",sum);}	break;//	查看队列是否为空	case 4:{if(QueueEmpty(q) == true){printf("队伍为空\n");}else{printf("队伍还有数据,不为空\n"); }}break;//	插入队列元素 case 5:{int s;printf("请输入你要添加到就诊队伍的病历号:\n");scanf("%d",&s);q = Push(q,s);		//	把输入的数据插入队列中 printf("添加成功!\n");	} break;//	就诊	case 6:{ElementType count1;Node *Link1;Link1 = q->head;			//	取队头指针 count1 = Link1->data;		//	队头指针指向内容取值 q->head = Link1->next;		//	让队头指针移到下一个节点 free(Link1);				//	释放刚才那个头节点printf("第%d 个患者开始就诊,病历号为: %d\n",++num,count1);if(QueueEmpty(q) == true)	//	判断队伍是否还有人 {printf("病人已经全部就诊完毕\n");break; }}break;//	查看(相当于出队) case 7:{int flag1;int i=0; while(1){flag1 = Pop(&S_Queue);if(flag1 == -1){printf("查看完毕完毕\n");	break;}else{printf("第%d 个患者病历号为: %d\n",++i,flag1);}}		}break;//	下班	case 8:printf("工作结束,打卡下班\n");exit(-1);		//	结束进程 default:printf("选择功能错误,请重新选择!!!!\n");break;}}return 0;
}

学习笔记,欢迎交流,共同进步

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

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

相关文章

《统计学简易速速上手小册》第6章:多变量数据分析(2024 最新版)

文章目录 6.1 主成分分析&#xff08;PCA&#xff09;6.1.1 基础知识6.1.2 主要案例&#xff1a;客户细分6.1.3 拓展案例 1&#xff1a;面部识别6.1.4 拓展案例 2&#xff1a;基因数据分析 6.2 聚类分析6.2.1 基础知识6.2.2 主要案例&#xff1a;市场细分6.2.3 拓展案例 1&…

第2讲投票系统后端架构搭建

创建项目时&#xff0c;随机选择一个&#xff0c;后面会生成配置properties文件 生成文件 maven-3.3.3 设置阿里云镜像 <?xml version"1.0" encoding"UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more cont…

【Python】Mac 本地部署 stable-diffusion

其实要在本地部署 stable-diffusion 不难&#xff0c;只要有“魔法”一切都水到渠成&#xff0c;如下图&#xff1a; (base) MacBook-Pro python % git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui Cloning into stable-diffusion-webui... remote: Enu…

前端JavaScript篇之setTimeout、Promise、Async/Await 的区别

目录 setTimeout、Promise、Async/Await 的区别**setTimeout**:思路需要注意的 **Promise**:思路需要注意的 **Async/Await**:思路需要注意的 总结 setTimeout、Promise、Async/Await 的区别 setTimeout: 概念&#xff1a;setTimeout是JavaScript中的一个函数&#xff0c;用于…

c++求三个数中最大数

#include<iostream> using namespace std; int main() { int a,b,c; cout<<"请输入三个数字"<<endl;//end后面为小写的L cin>>a>>b>>c; if(a>b&&a>c) cout<<"最大数为a:"<<a<<e…

【MySQL】——数值函数的学习

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-Z1fAnfrxGD7I5gqp {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

JAVA设计模式之访问模式详解

访问者模式 1 访问者模式介绍 访问者模式在实际开发中使用的非常少,因为它比较难以实现并且应用该模式肯能会导致代码的可读性变差,可维护性变差,在没有特别必要的情况下,不建议使用访问者模式. 访问者模式(Visitor Pattern) 的原始定义是&#xff1a;允许在运行时将一个或多…

Java集合 LinkedList

目录 LinkedList实例 LinkedList LinkedList是Java中的一个重要的数据结构&#xff0c;它实现了List接口&#xff0c;提供了链表数据结构的实现。LinkedList类中包含了各种常用的链表操作&#xff0c;如添加、删除、查找等。 LinkedList的特点是元素可以动态地添加到链表的任…

关于创建vue项目报错command failed: npm install --loglevel error

一、首先 在这个目录下有个文件叫.vuerc 二、其次 进去之后把里面的"useTaobaoRegistry": false,修改下&#xff0c;我之前是true&#xff0c;后来改成了false才成功。

【数据结构】11 堆栈(顺序存储和链式存储)

定义 可认为是具有一定约束的线性表&#xff0c;插入和删除操作都在一个称为栈顶的端点位置。也叫后入先出表&#xff08;LIFO&#xff09; 类型名称&#xff1a;堆栈&#xff08;STACK&#xff09; 数据对象集&#xff1a; 一个有0个或者多个元素的有穷线性表。 操作集&#…

单片机与外设的交互

单片机与外设的交互是嵌入式系统中非常重要的一个基础知识点。单片机是一个集成在同一芯片上的中央处理器、存储器和输入/输出接口,它可以根据用户编写的程序与各种外部设备即外设进行交互。单片机与外设之间的交互主要通过单片机上的输入/输出口(I/O口)来实现。 I/O口的工作原…

一个适用于后渗透期间的信息收集工具

介绍 Pillager是一个适用于后渗透期间的信息收集工具&#xff0c;可以收集目标机器上敏感信息&#xff0c;方便下一步渗透工作的进行。 支持 注&#xff1a;✅表示经过测试&#xff0c;&#x1f6a7;表示理论上支持但未经测试&#xff0c;❌表示无此功能或不支持 后续将会陆续…

CSP-202006-1-线性分类器

CSP-202006-1-线性分类器 解题思路 通过比较第一个训练数据点的类别和直线函数值的正负来确定标准类别和标准函数值的正负。循环遍历训练数据中的每个点&#xff0c;计算直线函数值并与标准函数值比较&#xff0c;以确定该点所在的类别。 如果当前点的类别与标准类别一致&…

Lua: 一门轻量级、高效的脚本语言

Lua: 一门轻量级、高效的脚本语言 在当今软件开发的领域中&#xff0c;寻找一门既灵活又高效的脚本语言&#xff0c;一直是开发者们追求的目标。Lua作为一门小巧、高效、可嵌入的脚本语言&#xff0c;已经成为了众多开发者的首选之一。无论是游戏开发、嵌入式系统、Web 开发还是…

ncc匹配提速总结

我们ncc最原始的匹配方法是&#xff1a;学习模板w*h个像素都要带入ncc公式计算 第一种提速&#xff0c;学习模板是w*h&#xff0c;而我们支取其中的w/2*h/2,匹配窗口同理&#xff0c;计算量只有1/4。 另外一种因为ncc是线性匹配&#xff0c;我们在这上面也做了文章&#xff0…

《UE5_C++多人TPS完整教程》学习笔记2 ——《P3 多人游戏概念(Multiplayer Concept)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P3 多人游戏概念&#xff08;Multiplayer Concept&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译…

如何把手机平板变为电脑的屏幕

文章目录 安装软件运行效果结尾 本文首发地址 https://h89.cn/archives/181.html 最新更新地址 https://gitee.com/chenjim/chenjimblog 闲置的手机平板、触屏音箱等&#xff0c;均可作为电脑的扩展屏&#xff0c;为电脑增加一块显示屏&#xff0c;本文介绍如何使用免费的软件s…

DS Wannabe之5-AM Project: DS 30day int prep day12

Q1. Where is the confusion matrix used? Which module would you use to show it? 混淆矩阵 混淆矩阵常用于评估分类模型的性能&#xff0c;特别是在二分类或多分类问题中。它展示了实际类别与模型预测类别之间的关系。在Python中&#xff0c;可以使用sklearn.metrics模块…

代码随想录算法训练营DAY13 | 栈与队列 (3)

一、LeetCode 239 滑动窗口最大值 题目链接&#xff1a;239.滑动窗口最大值https://leetcode.cn/problems/sliding-window-maximum/ 思路&#xff1a;使用单调队列&#xff0c;只保存窗口中可能存在的最大值&#xff0c;从而降低时间复杂度。 public class MyQueue{Deque<I…

【闲谈】初识深度学习

在过去的十年中&#xff0c;深度学习彻底改变了我们处理数据和解决复杂问题的方式。从图像识别到自然语言处理&#xff0c;再到游戏玩法&#xff0c;深度学习的应用广泛且深入。本文将探讨深度学习的基础知识、关键技术以及最新的研究进展&#xff0c;为读者提供一个全面的视角…