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

代码参考《妙趣横生的算法.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;对…

Android开发和调试必备工具-SDK Tools

原文链接&#xff1a;http://android.eoe.cn/topic/android_sdk SDK Tools是Android SDK的一个可下载部分&#xff0c;它包括Android SDK的开发和调试的所有工具。 如果你刚刚了解SDK&#xff0c;你可以从SDK starter package下载最新版本的SDK。 如果你已经在使用SDK&#xff…

strictmath_Java StrictMath ceil()方法与示例

strictmathStrictMath类ceil()方法 (StrictMath Class ceil() method) ceil() method is available in java.lang package. ceil()方法在java.lang包中可用。 ceil() method is used to return the least or smallest value of the double type value which is greater than or…

web应用之文件上传

一、Jakart:Jakart文件上传&#xff1a;&#xff08;推荐使用&#xff09; import java.io.File;import java.io.IOException;import java.util.List; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletReq…

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

代码参考《妙趣横生的算法.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;所以今天给小伙伴…

linux技巧----查找某个正在执行的脚本

如果在机器上发现有执行的脚本&#xff0c;却不知道在哪&#xff0c;可以这样找 例如 # netstat -ltnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp …

成功沟通的六要素

沟通在我们的生活、工作中必不可少&#xff0c;成功的沟通有助于事业成功&#xff0c;家庭美满&#xff01;下面分享一篇关于沟通的文章&#xff0c;成功沟通六要素&#xff1a; 当蜘蛛网连接起来&#xff0c;可以捆住一头狮子。——埃塞俄比亚谚语 与他人合作使我们可以实现比…

java中intvalue_Java Number intValue()方法与示例

java中intvalueNumber类intValue()方法 (Number Class intValue() method) intValue() method is available in java.lang package. intValue()方法在java.lang包中可用。 intValue() method is used to return the value denoted by this Number object converted to type int…

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

该内容出自黑马程序员教程 采集最近一日世界各国疫情数据 步骤&#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五子棋的过程分为十四…

Java BigDecimal plus()方法与示例

BigDecimal Class plus()方法 (BigDecimal Class plus() method) Syntax: 句法&#xff1a; public BigDecimal plus();public BigDecimal plus(MathContext ma_co);plus() method is available in java.math package. plus()方法在java.math包中可用。 plus() method is used…

爬虫项目(二)---采集从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…

git 项目过大问题解决

当项目过大时&#xff0c;git clone时会出现error: RPC failed; HTTP curl The requested URL returned error: Gateway Time-out的问题 解决方法很简单&#xff0c;在git clone时加上--depth1即可解决 克隆的项目只包含最近的一次commit的一个分支&#xff0c;体积很小&#x…

java bitset_Java BitSet hashCode()方法及示例

java bitsetBitSet类hashCode()方法 (BitSet Class hashCode() method) hashCode() method is available in java.util package. hashCode()方法在java.util包中可用。 hashCode() method is used to retrieve hash code for this bit set (BitSet). hashCode()方法用于检索此位…

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

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