【数据结构基础笔记】【队列】

代码参考《妙趣横生的算法.C语言实现》

文章目录

  • 前言
    • 1、队列定义
    • 2、创建一个队列
    • 3、入队列
    • 4、出队列
    • 5、销毁一个队列
    • 6、循环队列的概念
    • 7、循环队列的实现
    • 8、实例分析


前言

本章总结:链队列定义,创建,出队入队操作,销毁操作;循环队列的定义以及循环队列的一些基本操作


1、队列定义

队列是一种先进先出的线性表(FIFO),它要求所有的数据从队列的一端进入,从队列的另一端离开。
在队列中,允许插入数据的一端角队尾,允许数据离开的一端叫做队头。
在这里插入图片描述
队列是一个线性表,既可以是一个顺序表也可以是一个链表。这里重点介绍用链表实现一个队列。

typedef char ElemType ;
//队列元素类,队列中的每个元素都是QNode类
typedef struct QNode{ElemType data;			//队列结点的数据域struct QNode* next;		//队列结点的指针域
}QNode, *QueuePtr;typedef struct {QueuePtr front;			//队头指针,用来存放队头元素的地址QueuePtr rear;			//队尾指针,用来存放队尾元素的地址
}LinkQueue;
//这里定义得队列是一个链队列,队列之间的元素由指针相连,所以只要掌握了队列的队头指针和队尾指针,就可以对队列进行各种

2、创建一个队列

创建一个队列要完成两步:
1、在内存中创建一个头结点,但该头结点不是用来存放数据的,而是为了操作方便人为添加的。
2、将队列的头指针和尾指针都指向这个生成的头结点,此时队列中没有任何队列元素,该队列为空队列。
这样判断队列为空的条件就是头指针front和尾指针rear都同时指向头结点。

//创建一个空队列
void InitQueue(LinkQueue* q)
{q->front = q->rear = (QueuePtr)malloc(sizeof(QNode));		//初始化一个队列指针大小的空间,并将地址传给头指针和尾指针if (!q->front){printf("内存分配失败");exit(0);}q->front->next = NULL;		//头结点指针域指向空
}

此时空队列的状态如下:
在这里插入图片描述

3、入队列

入队列就是讲一个QNode类型的结点从队列尾部进入队列。
每当一个队列元素插入队列,队列的尾指针都要进行修改。
队头的指针不改变。

//入队列
void EnQueue(LinkQueue* q,ElemType elem)
{QueuePtr p;p = (QueuePtr)malloc(sizeof(QNode));		//创建一个队列元素结点,并将地址传给指针pif (p == NULL){printf("分配内存失败");exit(0);}p->data = elem;			//将数据elem放到队列结点data域中p->next = NULL;q->rear->next = p;		//从队尾插入元素q->rear = p;			//修改队尾指针,注意,此时队尾指针指向空(q->rear->next = p->next =NULL)
}

入队列操作流程:
在这里插入图片描述

4、出队列

出队列操作就是将队列中的元素从队列的头部移除。每次从队列中一出数据时,队头指针front不改变,但是头结点的next指针要发生改变。队尾指针rear只有在(队头即队尾)的情况下才会改变,否则也不改变。

//出队列
void DeQueue(LinkQueue* q, ElemType *elem)
{QueuePtr p;//如果队列不为空,删除q的队头元素,用e返回其值if (q->front == q->rear) return;		//队列为空,返回p = q->front->next;				//p指向队列的第一个元素*elem = p->data;				//将队首元素数据传给eq->front->next = p->next;		//删除当前头结点if (q->rear == p) q->rear = q->front;		//如果此时队列为空,则修改队尾指针free(p);						//将原本队头结点销毁
}

效果如下:
1、当队伍中存在超过1个元素
在这里插入图片描述
2、当队伍中只有一个元素时
在这里插入图片描述

5、销毁一个队列

由于队列建立在内存动态区(堆内存),因此当一个队列不再有用时,应当把它及时销毁掉,以免占用内存空间得不到释放导致内存泄漏。
释放一块内存要做两点:1.释放指向它的指针。2.将该指针指向空

void DestroyQueue(LinkQueue* q)
{while (q->front)			//如果队列头指针还存在{q->rear = q->front->next;	//q->rear指向q->front的后继结点free(q->front);				//释放q->front,此时q->rear应该指向NULLq->front = q->rear;}
}

6、循环队列的概念

用顺序表实现的队列称为循环队列,此队列的空间是可以循环使用的。

循环队列一般来说有固定的容量。

如果不断地有元素入队列,同时又不断地有元素出队列,那么对于一般的链队列,只要队列不为空,头指针front和尾指针rear都不会改变,只有头指针的next指针和尾指针的前一个结点的next指针会发生变化,而且链队列的长度也会随着入出度列元素而不断变化。

循环队列,容量固定,队头指针和队尾指针都可以随着元素的入出队列而发生改变,这样循环队列逻辑上就是一个环形的存储空间,只要队列中有空单元未使用,就可以向队列中存放元素

所以循环队列可以作为缓冲池存储结构来存放数据。
在这里插入图片描述
该队列总容量为8B,实际长度为5B。这里规定循环队列头指针front始终指向队头元素,尾指针rear始终指向队尾元素的下一个空间。
这里队头元素:f,队尾元素:b,该队列实际可用空间为7B。
在这里插入图片描述
将队首元素f出队列,在队尾加入元素a,形成上面队列。

所以,入队列操作就是想rear指向的空间赋值,rear再指向队尾元素的下一个空间。

出队列就是将队头指针front向上移一个单元。整个循环队列逻辑上就是一个首尾相接的环形缓冲区。

7、循环队列的实现

现实中只有线性的存储单元,不存在环形存储单元。

只需要注意rear不断加1后超过循环队列的地址范围,采用取模运算处理的结果。

因此,无论是入队列的rear+1操作还是出队列的front+1操作,实际都是模加运算,即

(rear+1)%len 和(front+1)%len

/*****************************循环队列******************************************/
//定义一个循环队列
#define MAXQSIZE 100
typedef struct {ElemType* base;			//循环队列内存分配基地址int front;				//队头int rear;				//队尾
}cycleQueue;				//循环队列类cycleQueue//初始化一个循环队列
void InitcycleQueue(cycleQueue *q)
{q->base = (ElemType*)malloc(MAXQSIZE*sizeof(ElemType));//开辟MAXQSIZE个单元的顺序表作为循环队列的存储空间if (!q->base){printf("循环队列分配内存失败");exit(0);}q->front = q->rear = 0;		//空队列,front和rear都指向0号单元}
//入队列操作
void EncycleQueue(cycleQueue* q, ElemType elem)
{if ((q->rear + 1) % MAXQSIZE == q->front)	return;	//循环队列已满q->base[q->rear] = elem;		//将元素elem入队列,q->base为顺序表的额首地址q->rear = (q->rear + 1) % MAXQSIZE;		//队尾指针+1,注意这里的全部都是模加运算
}
//出队列操作
void DecycleQueue(cycleQueue* q, ElemType* elem)
{if (q->front == q->rear)	return;				//循环队列为空*elem = q->base[q->front];						//取出队头元素q->front = (q->front + 1) % MAXQSIZE;			//队头指针+1
}

8、实例分析

实现一个链队列,任意输入一串字符,以@为结束标志,然后将队列中的元素逐一取出,打印出来

#include "stdio.h"
#include "malloc.h"
#include "conio.h"
#include <stdlib.h>
#include <math.h>
typedef char ElemType ;
/*****************************链队列******************************************/
//队列元素类,队列中的每个元素都是QNode类
typedef struct QNode{ElemType data;			//队列结点的数据域struct QNode* next;		//队列结点的指针域
}QNode, *QueuePtr;typedef struct {QueuePtr front;			//队头指针,用来存放队头元素的地址QueuePtr rear;			//队尾指针,用来存放队尾元素的地址
}LinkQueue;
//这里定义得队列是一个链队列,队列之间的元素由指针相连,所以只要掌握了队列的队头指针和队尾指针,就可以对队列进行各种操作。、//创建一个空队列
void InitQueue(LinkQueue* q)
{q->front = q->rear = (QueuePtr)malloc(sizeof(QNode));		//初始化一个队列指针大小的空间,并将地址传给头指针和尾指针if (!q->front){printf("内存分配失败");exit(0);}q->front->next = NULL;		//头结点指针域指向空
}
//入队列
void EnQueue(LinkQueue* q,ElemType elem)
{QueuePtr p;p = (QueuePtr)malloc(sizeof(QNode));		//创建一个队列元素结点,并将地址传给指针pif (p == NULL){printf("分配内存失败");exit(0);}p->data = elem;			//将数据elem放到队列结点data域中p->next = NULL;q->rear->next = p;		//从队尾插入元素q->rear = p;			//修改队尾指针,注意,此时队尾指针指向空(q->rear->next = p->next =NULL)
}
//出队列
void DeQueue(LinkQueue* q, ElemType *elem)
{QueuePtr p;//如果队列不为空,删除q的队头元素,用e返回其值if (q->front == q->rear) return;		//队列为空,返回p = q->front->next;				//p指向队列的第一个元素*elem = p->data;				//将队首元素数据传给eq->front->next = p->next;		//删除当前头结点if (q->rear == p) q->rear = q->front;		//如果此时队列为空,则修改队尾指针free(p);						//将原本队头结点销毁
}//销毁一个队列
//释放一块内存要做两点:1.释放指向它的指针。2.将该指针指向空
void DestroyQueue(LinkQueue* q)
{while (q->front)			//如果队列头指针还存在{q->rear = q->front->next;	//q->rear指向q->front的后继结点free(q->front);				//释放q->front,此时q->rear应该指向NULLq->front = q->rear;}
}/*****************************循环队列******************************************/
//定义一个循环队列
#define MAXQSIZE 100
typedef struct {ElemType* base;			//循环队列内存分配基地址int front;				//队头int rear;				//队尾
}cycleQueue;				//循环队列类cycleQueue//初始化一个循环队列
void InitcycleQueue(cycleQueue *q)
{q->base = (ElemType*)malloc(MAXQSIZE*sizeof(ElemType));//开辟MAXQSIZE个单元的顺序表作为循环队列的存储空间if (!q->base){printf("循环队列分配内存失败");exit(0);}q->front = q->rear = 0;		//空队列,front和rear都指向0号单元}
//入队列操作
void EncycleQueue(cycleQueue* q, ElemType elem)
{if ((q->rear + 1) % MAXQSIZE == q->front)	return;	//循环队列已满q->base[q->rear] = elem;		//将元素elem入队列,q->base为顺序表的额首地址q->rear = (q->rear + 1) % MAXQSIZE;		//队尾指针+1,注意这里的全部都是模加运算
}
//出队列操作
void DecycleQueue(cycleQueue* q, ElemType* elem)
{if (q->front == q->rear)	return;				//循环队列为空*elem = q->base[q->front];						//取出队头元素q->front = (q->front + 1) % MAXQSIZE;			//队头指针+1
}//测试函数
int main()
{ElemType e;LinkQueue q;InitQueue(&q);		//初始化一个队列qprintf("请输入一串字符到队列中\n");scanf("%c",&e);while (e != '@'){EnQueue(&q,e);scanf("%c", &e);}printf("队列为:\n");while (q.front != q.rear){DeQueue(&q, &e);printf("%c",e);}printf("\n");DestroyQueue(&q);		//销毁队列q_getche();return 0;
}

效果:
在这里插入图片描述

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

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

相关文章

html图片自动循环轮播图,js实现图片无缝循环轮播

本文实例为大家分享了js实现图片无缝循环轮播的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下代码如下Document#container{overflow:hidden;width:400px;height:300px;margin:auto;}#front,#container{display:flex;flex-direction:row;}#container img{width:400px…

五、json模块

一、json模块的介绍 json模块是Python自带的模块&#xff0c;用于json和Python数据之间的相互转换 Json与Python数据类型的对应关系 JsonPythonobjectdictarrayliststringstrnumber(int)int,longnumber(real)floattrueTruefalseFalsenullNone [#中括号括起来的&#xff0c;对…

【数据结构基础笔记】【树】

代码参考《妙趣横生的算法.C语言实现》 文章目录前言1、树的概念2、二叉树3、二叉树的遍历4、创建二叉树5、实例分析前言 本章总结&#xff1a;树的概念、二叉树的创建、遍历 1、树的概念 树结构是以分支关系定义得一种层次结构。 树的定义&#xff1a;树是由n(n>0)个结点…

可以自动撑起的html样式,好好玩:CSS3抖动样式CSS Shake让你的网页酷炫起来

之前在一些网站发现了一个好玩的样式&#xff0c;就是鼠标移到网站LOGO上&#xff0c;logo会自动抖动起来&#xff0c;显得非常炫酷。我也是十分感兴趣。自从本站新添加了一个视觉设计的分类之后&#xff0c;我也是想起来有个抖动CSS样式CSS Shake&#xff0c;所以今天给小伙伴…

爬虫项目(一)---采集最近一日世界各国的疫情数据信息

该内容出自黑马程序员教程 采集最近一日世界各国疫情数据 步骤&#xff1a; 发送请求&#xff0c;获取疫情首页从疫情首页中提取最近一日各国疫情字符串从最近一日各国疫情字符串中提取json格式字符串把json格式字符串转换为Python类型把Python类型的数据&#xff0c;以json…

【数据结构基础应用】【顺序表】

代码参考《妙趣横生的算法.C语言实现》、《剑指OFFER 名企面试官精讲典型编程题 第2版》等 文章目录前言1、合并两个顺序表前言 本章总结在看书过程中的一些关于顺序表的算法题并可能含有一些自己的一些疑问。题目数量不定&#xff0c;随阅历增加而增加&#xff1b; 1、合并两…

html上下滚动切换顶端tab,jQuery实现Tab菜单滚动切换的方法

本文实例讲述了jQuery实现Tab菜单滚动切换的方法。分享给大家供大家参考。具体如下&#xff1a;这是一款jQuery实现让你的Tab菜单滚动的代码,先运行一下看看效果咋样?是不是超不错,让你的网页变得灵动起来,不再静止,学习jquery的朋友也可作为范例来参考吧.运行效果截图如下&am…

[转载]十四步实现拥有强大AI的五子棋游戏

又是本人一份人工智能作业……首先道歉&#xff0c;从Word贴到Livewrter&#xff0c;好多格式没了&#xff0c;也没做代码高亮……大家凑活着看……想做个好的人机对弈的五子棋&#xff0c;可以说需要考虑的问题还是很多的&#xff0c;我们将制作拥有强大AI五子棋的过程分为十四…

爬虫项目(二)---采集从03月02号以来的世界各国疫情数据

该内容出自黑马程序员教程 采集从03月02号以来的世界各国疫情数据 步骤&#xff1a; Ⅰ&#xff0c;重构项目(一)的代码&#xff0c;以提高扩展性 把功能封装到一个类中每一个小功能变成一个方法通过run方法启动爬虫 import requests import re import json from bs4 impor…

【原创】StreamInsight查询系列(二十)——查询模式之检测间隙事件

上篇文章介绍了查询模式中如何检测异常事件&#xff0c;这篇博文将介绍StreamInsight中如何检测间隙事件。 测试数据准备 为了方便测试查询&#xff0c;我们首先准备一个静态的测试数据源&#xff1a;// 创建数据源&#xff0c;要注意的是4:16和4:30之间存在的事件间隙 var sou…

【数据结构基础应用】【查找和排序算法】

代码参考《妙趣横生的算法.C语言实现》 文章目录前言1、顺序查找2、折半查找3、直接插入排序4、选择排序5、冒泡排序6、希尔排序7、快速排序8、堆排序9、排序算法性能比较10、所有算法的code&#xff08;C语言&#xff09;前言 本章总结查找和排序算法&#xff1a;顺序查找、折…

爬虫项目(三)---采集最近一日全国各省疫情数据

该内容出自黑马程序员教程 采集最近一日全国各省疫情数据 当然&#xff0c;数据来源仍然是丁香园新型冠状病毒肺炎疫情实时动态首页 url&#xff1a;https://ncov.dxy.cn/ncovh5/view/pneumonia 思路&#xff1a;首先需要先确定全国各省疫情数据的位置 全国各省份的疫情数据…

计算机专业博士后排名,排名丨计算机专业领域TOP10,性价比超高!

原标题&#xff1a;排名丨计算机专业领域TOP10&#xff0c;性价比超高&#xff01;相信各位家长、同学已经看过太多专业的排名&#xff0c;我问过很多理科生将来想学什么专业&#xff0c;听到频率最高的还是计算机专业。似乎大家都知道&#xff0c;学计算机是比较挣钱的&#x…

js 命名规范

转载于:https://www.cnblogs.com/zjx2011/p/3165043.html

爬虫项目(四)---采集从01月22日以来全国各省疫情数据

采集从03月02日以来全国各省疫情数据 当然&#xff0c;数据来源仍然是丁香园新型冠状病毒肺炎疫情实时动态首页 url&#xff1a;https://ncov.dxy.cn/ncovh5/view/pneumonia 分析 确定01月22日以来全国各省疫情数据的URL 由项目(三)可以获取全国各省疫情数据点击可下载&…

纠错码trick和数据压缩trick

纠错码和压缩算法是同一枚硬币的两面。 两者都来自于对冗余的想法。 纠错码被视为向消息或文件中添加冗余的原则性方法。而压缩算法正好相反&#xff0c;他们会从消息或文件中移除冗余。 压缩和纠错并不是彼此抵消的&#xff0c;相反&#xff0c;好的压缩算法会移除抵消冗余&am…

常用算法总结(穷举法、贪心算法、递归与分治算法、回溯算法、数值概率算法)

博主联系方式&#xff1a; QQ:1540984562 QQ交流群&#xff1a;892023501 群里会有往届的smarters和电赛选手&#xff0c;群里也会不时分享一些有用的资料&#xff0c;有问题可以在群里多问问。 目录1、穷举法2、贪心算法3、递归与分治算法4、回溯算法5、数值概率算法1、穷举法…

工程师英语和计算机证书查询,点击进入国家硬件维修工程师证书查询网站

工程师证书查询网站人力资源社会保障部指定查询国家职业资格证书的唯一官方网站。涵盖全国各省市、各行业、各央企颁发的证书。电脑硬件维修工程师网上能查看国家工信部硬件维修工程师证书查询网址&#xff1a;http://www.ceiaec.org/index.htm工程师证书编号在网上怎么查询如果…

敏捷开发“松结对编程”系列之七:问题集之一

本文是“松结对编程”系列的第七篇。&#xff08;之一&#xff0c;之二&#xff0c;之三&#xff0c;之四&#xff0c;之五&#xff0c;之六&#xff0c;之七&#xff0c;之八&#xff09;刚刚参加完MPD 2011深圳站&#xff0c;在演讲中间及后来媒体采访&#xff0c;被问到了一…

C++中的sort函数对二维数组排序是按照什么准则?

遇到的一个疑惑&#xff0c;现记录如下&#xff1a; int main() {vector<vector<int>> envelopes { {5, 8},{6, 7},{6, 4},{2, 3},{8,9} };sort(envelopes.begin(), envelopes.end());for (int i 0;i < envelopes.size();i)cout << envelopes[i][0]<…