实验八 队列(循环队列)的表示和实现
- 格式:doc
- 大小:73.50 KB
- 文档页数:6
实验目的:通过本次实验,掌握循环队列的基本概念和操作方法,了解其在实际应用中的优势,并能够熟练运用循环队列解决实际问题。
实验环境:操作系统:Windows 10编程语言:C语言开发环境:Visual Studio实验内容:1. 循环队列的定义及初始化2. 循环队列的入队操作3. 循环队列的出队操作4. 循环队列的判空操作5. 循环队列的判满操作6. 循环队列的遍历操作7. 循环队列的应用实例实验步骤:一、循环队列的定义及初始化1. 定义循环队列的数据结构:```c#define MAX_SIZE 100 // 定义队列的最大容量typedef struct {int data[MAX_SIZE]; // 存储队列元素的数组int front; // 队头指针int rear; // 队尾指针} CircleQueue;```2. 初始化循环队列:```cvoid InitQueue(CircleQueue q) {q->front = q->rear = 0; // 初始化队头和队尾指针}```二、循环队列的入队操作1. 判断队列是否已满:```cint IsFull(CircleQueue q) {return (q->rear + 1) % MAX_SIZE == q->front;}```2. 入队操作:```cint EnQueue(CircleQueue q, int e) {if (IsFull(q)) {return 0; // 队列已满,无法入队}q->data[q->rear] = e; // 将元素e入队q->rear = (q->rear + 1) % MAX_SIZE; // 更新队尾指针return 1; // 入队成功}```三、循环队列的出队操作1. 判断队列是否为空:```cint IsEmpty(CircleQueue q) {return q->front == q->rear;}```2. 出队操作:```cint DeQueue(CircleQueue q, int e) {if (IsEmpty(q)) {return 0; // 队列为空,无法出队}e = q->data[q->front]; // 将队头元素出队q->front = (q->front + 1) % MAX_SIZE; // 更新队头指针 return 1; // 出队成功}```四、循环队列的判空操作1. 判断队列是否为空:```cint IsEmpty(CircleQueue q) {return q->front == q->rear;}```五、循环队列的判满操作1. 判断队列是否已满:```cint IsFull(CircleQueue q) {return (q->rear + 1) % MAX_SIZE == q->front; }```六、循环队列的遍历操作1. 遍历循环队列:```cvoid TraverseQueue(CircleQueue q) {if (IsEmpty(q)) {printf("队列为空,无法遍历。
数据结构实验报告姓名:方钢学号:20105567 专业:电子商务班级:10—1班指导教师:实验时间:实验地点:新区实验楼四楼(实验题目)循环队列1.实验内容和要求1.1实验要求①本次实验中,队列使用顺序结构循环队列;②结构定义和运算实验放入库文件“seqQueue.h”中;③各运算和变量命名直观易懂,并有相应的注释。
1.2实验内容<1>初始化一个队列。
<2>判断是否队空。
<3>判断是否队满。
<4>入队<5>出队<6>取队头元素<7>求当前队列中元素个数<8>编写算法实现①初始化空循环队列;②当键盘输入奇数时,此奇数入队;③当键盘输入偶数时,队头出队;④当键盘输入0时,算法退出;⑤每当键盘输入后,输出当前队列中的所有元素2.实验目的①掌握队列的基本概念。
②掌握循环队列的建立、入队和出队等方法。
③根据具体问题的需要,设计出合理的表示数据的结构,并设计相关算法。
3.算法设计<1>初始化一个队列。
<2>判断是否队空。
<3>判断是否队满。
<4>入队<5>出队<6>取队头元素<7>求当前队列中元素个数算法:int main(int argc, char* argv[]){seqQueue L;elementType x;int k,m,n;initQueue(&L);// 初始化顺序循环队列if(queueEmpty(L))// 判断空队列cout<<"当前队列空!"<<endl;elsecout<<"当前队列非空!"<<endl;cout<<"请输入入队元素的最大元素x=";cin>>x;if(x<MaxLen){while(x!=0){enQueue(&L, x);//循环入队for(m=x-1;m>=0;m--){break;}x=m;}cout<<"当前队列中元素(从头至尾):"; int i=L.front+1;while(i<=L.rear){cout<<L.data[i]<<", ";i++;}cout<<endl;cout<<"队列中元素个数为:";n=(L.rear-L.front+MaxLen)%MaxLen;cout<<n;cout<<endl;queueFront(L, x); // 取队头元素 cout<<"当前队头元素: x="<<x<<endl;outQueue(&L); // 出队(删除)cout<<"出队后队列中元素(从头至尾):";i=L.front+1;while(i<=L.rear){cout<<L.data[i]<<", ";i++;}cout<<endl;}elsecout<<"I'm sorry<<endl";return 0;}截图:<8>编写算法实现①初始化空循环队列;②当键盘输入奇数时,此奇数入队;③当键盘输入偶数时,队头出队;④当键盘输入0时,算法退出;⑤每当键盘输入后,输出当前队列中的所有元素算法:int main(int argc, char* argv[]){seqQueue L;elementType x;initQueue(&L);// 初始化顺序循环队列if(queueEmpty(L))// 判断空队列cout<<"当前队列空!"<<endl;elsecout<<"当前队列非空!"<<endl;cout<<"请输入入队元素:"<<endl;cin>>x;while(x!=0){if(x%2!=0){enQueue(&L, x);}elseoutQueue(&L);cout<<"当前队列中元素(从头至尾):"; int i=L.front+1;while(i<=L.rear){cout<<L.data[i]<<", ";i++;}cout<<endl;cin>>x;}while(x==0){cout<<"退出程序"<<endl;break;}return 0;}截图:4.总结和心得通过对循环队列的上机实验明白了循环队列的一些功能,对循环队列有了更深刻的了解。
浙江大学城市学院实验报告课程名称数据结构基础实验项目名称实验八队列(循环队列)的表示和实现学生姓名专业班级学号实验成绩指导老师(签名)日期2014-11-27一.实验目的和要求1、掌握队列的存储结构及基本操作。
2、掌握循环队列的设置及循环队列的各种基本操作的实现。
3、通过具体的应用实例,进一步熟悉和掌握队列的实际应用。
二.实验内容1、建立头文件SeqQueue.h,定义顺序存储的循环队列存储结构,并编写循环队列的各种基本操作实现函数。
同时建立一个验证操作实现的主函数文件test3_2.cpp,编译并调试程序,直到正确运行。
2、选做:编写程序,实现舞伴问题。
假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队,跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴,若两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。
要求设计一个函数void partner(),模拟上述舞伴配对问题。
基本要求:1) 由键盘输入数据,每对数据包括姓名和性别;2) 输出结果包括配成舞伴的女士和男士的姓名,以及未配对者的队伍名称和队头者的姓名;3) 要求利用SeqQueue.h中已实现的顺序循环队列的基本操作函数来实现。
函数void partner() 添加到文件test3_2.cpp中,在主函数中进行调用测试。
3、填写实验报告,实验报告文件取名为report8.doc。
4、上传实验报告文件report8.doc、源程序文件test3_2.cpp及SeqQueue.h 到Ftp服务器上自己的文件夹下。
三. 函数的功能说明及算法思路抽象数据类型:ADT SET isData:一个队列Q,假定用标示符Queue表示队列的存储类型Operation:void InitQueue(Queue& Q)//初始化队列为空并带有动态存储空间分配int EmptyQueue(Queue Q)//判断队列是否为空,空返回1,否则返回0void EnQueue(Queue& Q , ElemType item )//向队列插入元素,若队列已满重新分配更大的存储空间ElemType OutQueue(Queue& Q)//从队列中删除元素并返回ElemType PeekQueue(Queue Q)//读取队首元素,不改变队列状态void ClearQueue(Queue &Q)//清除队列为空,并释放动态存储空间void partner(Queue a,Queue b)//实现解决舞伴问题end QUEUE存储结构:typedef char ElemType;struct Queue{ //动态分配ElemType *queue;int front,rear;//队头指针,队尾指针int MaxSize;//队列最大存储数};struct Dancer{ //存储舞者的姓名和性别char name;char sex;};解决舞伴问题分析:void partner(Queue a,Queue b)建立两个队列a和b,a放女生,b放男生。
队列的理解和实现(⼀)-----循环队列(java实现)什么是队列我们都知道栈是先进后出的⼀种线性表,与之相反的是,队列是⼀种先进先出的线性表。
它只允许在表的⼀端进⾏插⼊,⽽在另⼀端进⾏删除。
举个例⼦来说,在⽣活中我们买东西需要进⾏排队,最先排队的可以最早的离开队伍,⽽排在最后⾯的需要最后离开队伍。
在队列当中,允许插⼊的⼀端称为队尾,⽽允许删除的⼀段称为队头。
和栈与线性表类似,队列也分为顺序队列和链队列。
普通队列所存在的问题在使⽤数组实现的队列中,⼊队的操作就是将尾指针rear右移⼀个单位(加⼀),然后将元素值赋值给rear单位。
出队时,则是头指针front 后移⼀个单位(加⼀)。
当进⾏了⼀定数量的⼊队和出队操作后,可能会出现这样的情况:尾指针rear已指到数组的最后有⼀个元素,即rear=maxSize-1,此时若再数组的前⾯部分可能还有很多闲置空间,即这种溢出并⾮是真的没有可⽤的存储空间,故称这种溢出现象为“假溢出”。
显然,必须要解决这⼀块假溢出的问题,否则顺序队列就没有太多使⽤价值。
解决假溢出⼀般情况下有两个⽅式:1.在普通队列中设置元素实际个数变量size,在每次⼊队或者出队时将size和maxSize进⾏⽐较,从⽽避免假溢出。
使⽤这种⽅式未免有些繁琐。
2.使⽤循环队列,将队列掰弯,也就是将队列看成环状结构,即data[0]为紧接着data[MaxLen-1]的单元,为相邻的元素,⾸位成为⼀个环,如下所⽰:理解循环队列⾸先要确认的是,循环队列仍然是基于数组实现的,使⽤⼀组地址连续的存储单元依次存放从队头到队尾的元素,且仍然设置两个指针front,rear。
注意的是,其实这两个指针是整数型的,起得是知识的作⽤便于理解,所以称之为指针。
这两个指针,⼀个指着队头,⼀个指着队尾。
这两个指针可以看做动态的过程,即这两个指针其实是互相追赶的。
在追赶中就是队列中元素添加和删除的过程。
当rear追到front时就表⽰队列已经满了,当front追上rear时就表⽰队列已经空了。
循环队列的学习解析以及C语言实现首先我们先来了解一下队列的概念:队列是一种先进先出的线性表只能在表头删除在表尾插入,操作系统的作业队列就是队列的一个很好的应用。
也有可以在两端均可进行插入和删除操作的队列,称为双端队列,但其用处并没有一般队列广泛。
ADT Queue {数据对象:D={ai | ai∈ElemSet, i=1,2,...,n, n≥0} 数据关系:R1={ <a i-1,ai > | ai-1, ai ∈D, i=2,...,n} (约定其中a1端为队列头,an端为队列尾)基本操作:InitQueue(&Q) 初始化队列DestroyQueue(&Q) 销毁队列QueueEmpty(Q) 判断队列空否QueueLength(Q) 求取队长GetHead(Q, &e) 取对头元素ClearQueue(&Q) 清空对列EnQueue(&Q, e) 入队一个元素DeQueue(&Q, &e) 出队一个元素QueueTravers(Q, visit()) 访问队列} ADT Queue队列也有两种存储结构,分别是顺序存储和链式存储。
队列的顺序结构和顺序表以及顺序栈的存储结构类似,他们所运用的都是一组地址连续的存储。
其中队列需要附设两个整形变量front 和rear 分别指示队列头元素和队列的尾元素的位置。
c b a 5 4 3 2 1 0 Q.rear →Q.fron → Q.rea → Q.fron→(1)空队列 (2)a,b,,c 相继入队由于顺序队列所分配的空间有限,根据队列入队和出队的特点可能发生“假溢出”现象,即队尾元素无法在前移。
解决的办法就是将队列抽象成为环状,即循环队列。
循环队列以下是循环队列的几种主要的操作以及C 语言实现:/********循环队列的数据结构***********/#define MAXQSIZE 10typedef struct{QElemType *base;int front;int rear; { 队空条件:Q.front=Q.rear队满条件:(Q.rear+1)%MAXQSIZE} SqQueue;1、循环队列的初始化Status InitQueue(SqQueue &Q){ //构建一个空队列Q.base = new QElemType[MAXQSIZE];if( Q.base = NULL) //存储分配失败exit(OVERFLOW) ;Q.front = Q.rear = 0; //头尾指针置为零,队列为空return OK;}2、求循环队列长度int QueueLength(Squeue Q){return (Q.rear - Q.front + MAXQSIZE )%MAXQSIZE; }3、入队Status EnQueue (SqQueue &Q , QElemType e){if((Q.rear+1)%MAXQSIZe == Q.front)return ERROW;Q.base[Q.rear] = e;Q.rear = (Q.rear + 1) %MAXQSIZE;return OK:}4、出队Status DeQueue(SqQueue &Q,QElemType &e)if(Q.front==Q.rear)return ERROW;e=Q.base[Q.front];Q.front = (Q.front + 1 )%MAXQSIZE; return OK;}5、取队头元素SElemType GetHead(SqQueue Q) {if(Q.front ! = Q.rear)return Q.base[Q.front];}队列的链式表示和实现。
C语⾔循环队列的表⽰与实现实例详解1.概述:C语⾔的队列(queue),是先进先出(FIFO, First-In-First-Out)的线性表数据结构。
在具体应⽤中通常⽤链表或者数组来实现。
队列只允许在后端(称为rear)进⾏插⼊操作,在前端(称为front)进⾏删除操作。
循环队列可以更简单的防⽌伪溢出的发⽣,但是队列⼤⼩是固定的。
2.实例代码:/* 队列的顺序存储结构(循环队列) */#define MAX_QSIZE 5 /* 最⼤队列长度+1 */typedef struct{QElemType *base; /* 初始化的动态分配存储空间 */int front; /* 头指针,若队列不空,指向队列头元素 */int rear; /* 尾指针,若队列不空,指向队列尾元素的下⼀个位置 */}SqQueue;/* 循环队列的基本操作(9个) */void InitQueue(SqQueue *Q){ /* 构造⼀个空队列Q */Q->base=malloc(MAX_QSIZE*sizeof(QElemType));if(!Q->base) /* 存储分配失败 */exit(OVERFLOW);Q->front=Q->rear=0;}void DestroyQueue(SqQueue *Q){ /* 销毁队列Q,Q不再存在 */if(Q->base)free(Q->base);Q->base=NULL;Q->front=Q->rear=0;}void ClearQueue(SqQueue *Q){ /* 将Q清为空队列 */Q->front=Q->rear=0;}Status QueueEmpty(SqQueue Q){ /* 若队列Q为空队列,则返回TRUE;否则返回FALSE */if(Q.front==Q.rear) /* 队列空的标志 */return TRUE;elsereturn FALSE;}int QueueLength(SqQueue Q){ /* 返回Q的元素个数,即队列的长度 */return(Q.rear-Q.front+MAX_QSIZE)%MAX_QSIZE;}Status GetHead(SqQueue Q,QElemType *e){ /* 若队列不空,则⽤e返回Q的队头元素,并返回OK;否则返回ERROR */if(Q.front==Q.rear) /* 队列空 */return ERROR;*e=Q.base[Q.front];return OK;}Status EnQueue(SqQueue *Q,QElemType e){ /* 插⼊元素e为Q的新的队尾元素 */if((Q->rear+1)%MAX_QSIZE==Q->front) /* 队列满 */return ERROR;Q->base[Q->rear]=e;Q->rear=(Q->rear+1)%MAX_QSIZE;return OK;}Status DeQueue(SqQueue *Q,QElemType *e){ /* 若队列不空,则删除Q的队头元素,⽤e返回其值,并返回OK;否则返回ERROR */if(Q->front==Q->rear) /* 队列空 */return ERROR;*e=Q->base[Q->front];Q->front=(Q->front+1)%MAX_QSIZE;return OK;}void QueueTraverse(SqQueue Q,void(*vi)(QElemType)){ /* 从队头到队尾依次对队列Q中每个元素调⽤函数vi() */int i;i=Q.front;while(i!=Q.rear){vi(Q.base[i]);i=(i+1)%MAX_QSIZE; }printf("\n");}。
用链表实现循环队列的方法循环队列是一种利用固定大小的数组实现队列的数据结构,它具有高效的空间利用率和灵活的数据处理能力。
在某些场景下,我们可以使用链表来实现循环队列,以便更好地满足特定需求。
本文将详细介绍如何用链表实现循环队列的方法。
一、链表循环队列的基本概念链表循环队列是一种基于链表实现的队列结构,它具备以下特点:1.链表中的节点包含两个域:数据域和指针域。
数据域存储队列中的元素,指针域存储指向下一个节点的指针。
2.链表循环队列具有头指针和尾指针,分别指向队列的第一个元素和最后一个元素。
3.链表循环队列的长度可以动态调整,不会受到固定数组长度的限制。
二、链表循环队列的初始化1.创建一个头节点,头节点的数据域可以不存储有效数据,仅作为队列的起始节点。
2.初始化头指针和尾指针,使它们都指向头节点。
3.初始化队列长度为0。
三、链表循环队列的基本操作1.入队操作:a.创建一个新节点,将新节点数据域设置为待入队的元素。
b.将尾指针指向的节点的指针域指向新节点。
c.更新尾指针,使其指向新节点。
d.队列长度加1。
2.出队操作:a.判断队列是否为空,若为空,则返回错误信息。
b.保存头指针指向的节点的数据域值。
c.更新头指针,使其指向下一个节点。
d.删除原头节点。
e.队列长度减1。
3.获取队首元素:a.判断队列是否为空,若为空,则返回错误信息。
b.返回头指针指向的节点的数据域值。
4.判断队列是否为空:a.判断头指针是否等于尾指针,若相等,则队列为空。
四、链表循环队列的优势1.空间利用率高:链表循环队列可以根据需求动态调整长度,有效避免内存浪费。
2.灵活性强:链表循环队列可以方便地实现队列的扩展和收缩,适应不同场景的需求。
3.数据处理高效:链表循环队列在入队和出队操作时,时间复杂度均为O(1),具有较高的处理效率。
总结:使用链表实现循环队列是一种高效、灵活的数据结构设计方法。
队列(循环队列的顺序实现)⼀、概述与栈相反,队列是先进先出(FIFO),后进后出的数据结构。
插⼊的⼀端叫做队尾,⽽出去的⼀端则称为队头或队⾸。
但是队列(Queue)有⼀种扩展形式,称为双端队列(Deque),即可以在两端都进⾏插⼊和删除的操作,看起来双端队列似乎更加使⽤,但在实际应⽤中却并不常见。
同样的,队列也有两种实现形式,即顺序队列和链队列。
链队列可以参考链栈,直接将出栈操作改成删除头节点即可,插⼊删除⽅便,适合栈和队列。
顺序队列当然是数组实现,顺序队列的问题在于出队时前⾯空出的位置是否由后⾯的元素补充,如果不补充,那么会造成空间极度的浪费,如果补充,那么需要将每个元素都向前移,时间复杂度此时来到O(N),为了解决这个问题,循环队列应运⽽⽣,即将补充的元素放到前⾯由于出队⽽造成的空缺位置。
这样就可以最⼤限度的利⽤已申请的空间。
⼆、顺序实现循环队列数据域:private int Capacity;private int front;private int rear;private int [] data;static int DEFAULT_SIZE = 6;public Queue(){front = rear = 0;Capacity = DEFAULT_SIZE;data = new int [Capacity];}由于JAVA并不⽀持泛型数组,因此我们以int型的队列作为⽰例。
这⾥简单描述⼀下循环队列的结构,⼀个空的循环队列如下图:当⼊队3个元素时变为:再出队1个元素接下来是求长度和判满空public int getSize(){return (rear - front + Capacity) % Capacity;}public boolean isEmpty(){return (rear == front);}public boolean isFull(){return ((rear + 1) % Capacity == front);}先说求元素个数(长度),从图中看起来好像直接返回rear-front即可,但是因为是循环队列,考虑下列情况:显然不能⽤简单的减法,必须将两种算法统⼀起来,因此(rear - front + Capacity) % Capacity正是起到这样的作⽤。
实现循环队列的入队出队等基本操作循环队列是一种特殊的队列数据结构,通过循环利用数组空间来实现入队和出队操作。
它的特点是队头和队尾可以在数组上循环移动,从而充分利用数组空间,提高队列的效率。
下面将详细介绍循环队列的实现。
1.定义循环队列的数据结构循环队列的数据结构由以下几个成员组成:-一个固定大小的数组,用于存储队列元素。
- 一个队头指针front,指向队列的第一个元素。
- 一个队尾指针rear,指向队列的最后一个元素的下一个位置。
2.初始化循环队列首先,我们需要在内存中分配一个固定大小的数组,并初始化队头和队尾指针为0。
```pythondef __init__(self, k: int):self.queue = [0] * kself.front = self.rear = 0```3.入队操作入队操作会在队尾插入一个新元素,并将队尾指针后移一位。
如果队列已满,则入队操作会失败。
```pythondef enqueue(self, value: int) -> bool:if self.isFull(:return Falseself.queue[self.rear] = valueself.rear = (self.rear + 1) % len(self.queue)return True```4.出队操作出队操作会删除队头元素,并将队头指针后移一位。
如果队列为空,则出队操作会失败。
```pythondef dequeue(self) -> bool:if self.isEmpty(:return Falseself.front = (self.front + 1) % len(self.queue)return True```5.判空操作判空操作会检查队头和队尾指针是否相等,如果相等则说明队列为空。
```pythondef isEmpty(self) -> bool:return self.front == self.rear```6.判满操作判满操作会检查队尾指针的下一位是否等于队头指针,如果相等则说明队列已满。
数据结构:循环队列及其基本操作的实现/*** 循环队列* 队列设置first指针直接指向队列头部元素,tail尾指针指向队列最后⼀个元素的后⼀个,即队列中总是预留⼀个空位*/class CircleQueue implements Queue<Integer>{private Integer[] queueArray = null;private int first;private int tail;private int maxSize;public CircleQueue(int max){this.maxSize=max+1;this.queueArray = new Integer[maxSize];}@Overridepublic int size() {return (tail-first+maxSize)%maxSize;}@Overridepublic boolean isEmpty() {return tail==first;}@Overridepublic boolean contains(Object o) {Integer integer = (Integer)o;for (int i = first; i!=tail; i++) {if (i==queueArray.length){i=0;}if (integer.equals(queueArray[i])){return true;}}return false;}@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {int temFirst = first;@Overridepublic boolean hasNext() {return tail!=temFirst;}@Overridepublic Integer next() {int num = queueArray[temFirst];temFirst = (temFirst+1)%maxSize;return num;}};}@Overridepublic boolean add(Integer integer) {if ((tail+1)%maxSize==first){System.out.println("队列已满,⽆法添加");return false;}queueArray[tail]=integer;tail = (tail+1)%maxSize;return true;}@Overridepublic Integer poll() {if(isEmpty()){throw new RuntimeException("队列为空");}int result = queueArray[first];first = (first+1)%maxSize;return first;}@Overridepublic Integer peek() {return queueArray[first];}}public static void main(String[] args) {CircleQueue circleQueue = new CircleQueue(5);Scanner scanner = new Scanner(System.in);while (true){System.out.println("1:添加元素");System.out.println("2:取出元素");System.out.println("3:查看头元素");System.out.println("4:遍历队列");System.out.println("5:查看元素数量");System.out.println("6:是否为空");int commend = scanner.nextInt();switch (commend){case 1:{System.out.println("请输出⼀个元素");int num = scanner.nextInt();circleQueue.add(num);break;}case 2:{System.out.println(circleQueue.poll());break;}case 3:{System.out.println(circleQueue.peek());break; }case 4:{for (Integer integer : circleQueue) {System.out.printf("%d\t",integer);}System.out.println();break;}case 5:{System.out.println(circleQueue.size());break; }case 6:{System.out.println(circleQueue.isEmpty());break;}}}}。
循环队列的基本操作及实现循环队列是一种基于数组实现的队列,它的特点是可以循环利用数组空间,避免了数组空间的浪费。
循环队列的基本操作包括入队、出队、判空、判满等,下面我们来详细介绍一下。
1. 入队操作入队操作是将元素添加到队列的末尾,也就是队尾。
在循环队列中,我们需要维护两个指针,一个指向队头,一个指向队尾。
当队列为空时,队头和队尾指针都指向数组的第一个位置。
当队列不为空时,队尾指针指向最后一个元素的下一个位置。
入队操作的实现如下:```void enqueue(int data) {if ((rear + 1) % MAX_SIZE == front) {printf("Queue is full.\n");return;}queue[rear] = data;rear = (rear + 1) % MAX_SIZE;}```2. 出队操作出队操作是将队头元素删除,并返回该元素的值。
在循环队列中,我们同样需要维护队头和队尾指针。
当队列为空时,无法进行出队操作。
出队操作的实现如下:```int dequeue() {if (front == rear) {printf("Queue is empty.\n");return -1;}int data = queue[front];front = (front + 1) % MAX_SIZE;return data;}```3. 判空操作判空操作是判断队列是否为空。
在循环队列中,当队头和队尾指针相同时,队列为空。
判空操作的实现如下:```bool isEmpty() {return front == rear;}```4. 判满操作判满操作是判断队列是否已满。
在循环队列中,当队尾指针的下一个位置等于队头指针时,队列已满。
判满操作的实现如下:```bool isFull() {return (rear + 1) % MAX_SIZE == front;}```以上就是循环队列的基本操作及实现。
循环队列详解及队列的顺序表⽰和实现循环队列——队列的顺序表⽰和实现前⾯分析顺序队的时候,我们知道,顺序队存在”假溢出”的问题,这个问题有时会造成很⼤的内存浪费,循环队列就是为了解决这个问题⽽提出地⼀个很巧妙的办法.循环队列和顺序队列的主要区别在于:循环队列将顺序队列臆造成⼀个环状空间.在操作上这种异同体现在:相同点:在顺序队列和循环队列中,进⾏出队、⼊队操作时,队⾸、队尾指针都要加 1 ,朝前移动。
不同点:1. 在循环队列中当队⾸、队尾指针指向向量上界(MAX_QUEUE_SIZE-1) 时,其加1 操作的结果是指向向量的下界 0 。
⽽在顺序队列中,说明队已满,若此时采⽤的是动态顺序链,可以增加申请内存.若是采⽤静态顺序链,只能退出程序.2. 顺序队列中q.front = q.rear 表⽰队空,q.rear = MAX_QUEUE_SIZE表⽰队满.⽽在循环队列中.front=q.rear表⽰队空,⽽⽆法⽤.rear=MAX_QUEUE_SIZE表⽰队满.判断循环队列队满的两种⽅法(本⽂采⽤第⼆种⽅法):1.另设⼀个标志位以区分队列是空还是满2.少⽤⼀个元素空间,约定以”队列头指针在队列尾指针的下⼀位置上”,作为队列呈满状态的标志.第⼆种⽅法的实现:◆ rear 所指的单元始终为空。
◆循环队列为空: front=rear 。
◆循环队列满: (rear+1)%MAX_QUEUE_SIZE=front 。
循环队列操作及指针变化情况如下图所⽰:循环队列虽然可以解决”假溢出”问题,但是它不能通过动态分配的⼀维数组来实现,所以在实现循环队列之前,⼀定要为它设定⼀个最⼤队列长度.如果⽆法预估所需的最⼤队列长度,只能采⽤来链表实现.代码实现:循环队列和顺序队列的头⽂件是⼀样的/* 循环队列的接⼝定义头⽂件 */#define true 1#define false 0/* 队的最⼤长度 */#define MAX_QUEUE_SIZE 6/* 队列的数据类型 */typedef int datatype;/* 静态链的数据结构 */typedef struct queue{datatype sp_queue_array[MAX_QUEUE_SIZE];/* 队头 */int front;/* 队尾 */int rear;}cir_queue;/* 静态顺序链的接⼝定义 *//* 静态链的初始化 */cir_queue queue_init();/* 判断队列是否为空,若为空* 返回true* 否则返回false*/int queue_empty(cir_queue q);/* 插⼊元素e为队q的队尾新元素* 插⼊成功返回true* 队满返回false*/int queue_en(cir_queue *q, datatype e);/* 队头元素出队* ⽤e返回出队元素,并返回true* 若队空返回false*/int queue_de(cir_queue *q, datatype *e);/* 清空队 */void queue_clear(cir_queue *q);/* 获得队头元素* 队列⾮空,⽤e返回队头元素,并返回true* 否则返回false*/int get_front(cir_queue, datatype *e );/* 获得队长 */int queue_len(cir_queue q);/* 遍历队 */void queue_traverse(cir_queue q, void(*visit)(cir_queue q)); void visit(cir_queue s);/* 循环队列的接⼝实现⽂件 */#include<stdio.h>#include<stdlib.h>#include"cir_queue.h"cir_queue queue_init(){cir_queue q;q.front = q. rear = 0;return q;}int queue_empty(cir_queue q){return q.front == q.rear;}int queue_en(cir_queue *q, datatype e){/* 判断队是否已满 */if (q -> front == (q -> rear + 1) % MAX_QUEUE_SIZE) return false;/* ⼊队 */q -> sp_queue_array[q -> rear] = e;q -> rear = (q -> rear + 1) % MAX_QUEUE_SIZE;return true;}int queue_de(cir_queue *q, datatype *e){/* 判断队列是否为空 */if(q -> front == q -> rear)return false;/* ⽤e返回队头元素 */*e = q -> sp_queue_array[q -> front];q -> front = (q -> front + 1 ) % MAX_QUEUE_SIZE;return true;}void queue_clear(cir_queue *q){q -> front = q -> rear = 0;}int get_front(cir_queue q, datatype *e){/* 判断队列是否为空 */if (q.front == q.rear)return false;*e = q.sp_queue_array[q.front];return true;}int queue_len(cir_queue q){/* 若front > rear */if(q.front > q.rear)return (q.rear + MAX_QUEUE_SIZE - q.front);elsereturn (q.rear - q.front);}void queue_traverse(cir_queue q, void(*visit)(cir_queue q)) {visit(q);}void visit(cir_queue q){while(q.front != q.rear){printf("%d ",q.sp_queue_array[q.front]);q.front = (q.front + 1) % MAX_QUEUE_SIZE;}}int main(){cir_queue q = queue_init();queue_en(&q, 1);queue_en(&q, 2);queue_en(&q, 3);queue_en(&q, 4);queue_en(&q, 5);printf("此时队长:length=%d\n", queue_len(q));queue_traverse(q, visit);printf("元素6再⼊队\n");queue_en(&q, 6);queue_traverse(q, visit);datatype *x = (datatype *)malloc(sizeof(*x));queue_de(&q,x);printf("出队:%d,此时队长=%d\n", *x, queue_len(q));printf("元素6再⼊队\n");queue_en(&q, 6);printf("length=%d\n", queue_len(q));queue_traverse(q,visit);datatype *e = (datatype *)malloc(sizeof(*e));queue_de(&q,e);printf("queue_de(),e=%d length=%d\n", *e, queue_len(q)); queue_traverse(q, visit);queue_clear(&q);queue_traverse(q, visit);printf("length:%d\n", queue_len(q));}运⾏截图:感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。
C语言循环队列的实现简介循环队列是一种常见的数据结构,它可以在固定大小的内存空间中实现高效的队列操作。
本文将介绍如何使用C语言实现循环队列,并提供一个基于循环语句的示例。
循环队列的定义循环队列是一种环形缓冲区,它通过前进和后退两个指针来实现队列操作。
在循环队列中,头指针指向队列的第一个元素,尾指针指向队列的最后一个元素的下一个位置。
循环队列的特点有:•在固定大小的内存空间中实现队列操作,有效地利用内存资源。
•通过头指针和尾指针的前进和后退操作,实现队列的插入和删除操作的时间复杂度为O(1)。
•当队列为空时,头指针和尾指针相等;当队列满时,头指针和尾指针相差为1。
循环队列的实现数据结构定义#define MAX_SIZE 10typedef struct {int data[MAX_SIZE];int front;int rear;} CircularQueue;•MAX_SIZE定义了循环队列的最大容量。
•data是循环队列的数据存储区,可以存储整型数据。
•front是头指针,指向队列的第一个元素。
•rear是尾指针,指向队列的最后一个元素的下一个位置。
初始化循环队列void initQueue(CircularQueue *queue) {queue->front = 0;queue->rear = 0;}初始化循环队列时,将头指针和尾指针都指向0,表示循环队列为空。
判断循环队列是否为空int isEmpty(CircularQueue *queue) {return (queue->front == queue->rear);}当头指针和尾指针相等时,循环队列为空。
判断循环队列是否已满int isFull(CircularQueue *queue) {return ((queue->rear + 1) % MAX_SIZE == queue->front); }当头指针和尾指针相差为1时,循环队列已满。
循环队列的基本操作及实现循环队列是一种经典的数据结构,它具有高效的插入和删除操作。
本文将介绍循环队列的基本操作及其实现。
一、循环队列的概念循环队列是一种环形的队列,它的特点是在队列的尾部插入新的元素时,如果队列已满,则插入到队列的头部。
这样可以实现队列的循环使用,避免了数据的搬移操作,提高了队列的效率。
二、循环队列的基本操作1. 初始化队列:创建一个容量为n的循环队列,并初始化队列的头指针front和尾指针rear,初始时front和rear均指向0。
2. 判断队列是否为空:当front和rear指向同一个位置时,表示队列为空。
3. 判断队列是否已满:当队列的下一个位置是front时,表示队列已满。
4. 入队操作:将新元素插入到队列的尾部,即将rear指针指向的位置赋值为新元素,并将rear指针后移一位。
如果队列已满,则插入失败。
5. 出队操作:将队列的头部元素删除,即将front指针后移一位。
如果队列为空,则删除失败。
6. 获取队列的头部元素:返回队列的头部元素,即返回front指针指向的位置的元素值。
三、循环队列的实现循环队列可以使用数组来实现,具体的实现代码如下:```class CircularQueue {constructor(capacity) {this.capacity = capacity;this.queue = new Array(capacity);this.front = 0;this.rear = 0;}isEmpty() {return this.front === this.rear;}isFull() {return (this.rear + 1) % this.capacity === this.front; }enqueue(element) {if (this.isFull()) {return false;}this.queue[this.rear] = element;this.rear = (this.rear + 1) % this.capacity; return true;}dequeue() {if (this.isEmpty()) {return null;}const element = this.queue[this.front];this.front = (this.front + 1) % this.capacity; return element;}getFront() {if (this.isEmpty()) {return null;}return this.queue[this.front];}}```四、循环队列的应用场景循环队列在实际应用中具有广泛的应用场景,例如操作系统中的进程调度、缓冲区管理、数据包处理等。
数据结构:循环队列(C语⾔实现)⽣活中有⾮常多队列的影⼦,⽐⽅打饭排队,买⽕车票排队问题等,能够说与时间相关的问题,⼀般都会涉及到队列问题;从⽣活中,能够抽象出队列的概念,队列就是⼀个能够实现“先进先出”的存储结构。
队列分为链式队列和静态队列;静态队列⼀般⽤数组来实现,但此时的队列必须是循环队列,否则会造成巨⼤的内存浪费;链式队列是⽤链表来实现队列的。
这⾥讲的是循环队列,⾸先我们必须明确以下⼏个问题⼀、循环队列的基础知识1.循环队列须要⼏个參数来确定循环队列须要2个參数,front和rear2.循环队列各个參数的含义(1)队列初始化时,front和rear值都为零;(2)当队列不为空时,front指向队列的第⼀个元素,rear指向队列最后⼀个元素的下⼀个位置;(3)当队列为空时,front与rear的值相等,但不⼀定为零;3.循环队列⼊队的伪算法(1)把值存在rear所在的位置;(2)rear=(rear+1)%maxsize ,当中maxsize代表数组的长度;程序代码:bool Enqueue(PQUEUE Q, int val){if(FullQueue(Q))return false;else{Q->pBase[Q->rear]=val;Q->rear=(Q->rear+1)%Q->maxsize;return true;}}4.循环队列出队的伪算法(1)先保存出队的值;(2)front=(front+1)%maxsize ,当中maxsize代表数组的长度;程序代码:bool Dequeue(PQUEUE Q, int *val){if(EmptyQueue(Q)){return false;}else{*val=Q->pBase[Q->front];Q->front=(Q->front+1)%Q->maxsize;return true;}}5.怎样推断循环队列是否为空if(front==rear)队列空;else队列不空;bool EmptyQueue(PQUEUE Q){if(Q->front==Q->rear) //推断是否为空return true;elsereturn false;}6.怎样推断循环队列是否为满这个问题⽐較复杂,如果数组的存数空间为7,此时已经存放1,a,5,7,22,90六个元素了,如果在往数组中加⼊⼀个元素,则rear=front;此时,队列满与队列空的推断条件front=rear同样,这种话我们就不能推断队列究竟是空还是满了;解决问题有两个办法:⼀是添加⼀个參数,⽤来记录数组中当前元素的个数;第⼆个办法是,少⽤⼀个存储空间,也就是数组的最后⼀个存数空间不⽤,当(rear+1)%maxsiz=front时,队列满;bool FullQueue(PQUEUE Q){if(Q->front==(Q->rear+1)%Q->maxsize) //推断循环链表是否满,留⼀个预留空间不⽤return true;elsereturn false;}附录:queue.h⽂件代码:#ifndef __QUEUE_H_#define __QUEUE_H_typedef struct queue{int *pBase;int front; //指向队列第⼀个元素int rear; //指向队列最后⼀个元素的下⼀个元素int maxsize; //循环队列的最⼤存储空间}QUEUE,*PQUEUE;void CreateQueue(PQUEUE Q,int maxsize);void TraverseQueue(PQUEUE Q);bool FullQueue(PQUEUE Q);bool EmptyQueue(PQUEUE Q);bool Enqueue(PQUEUE Q, int val);bool Dequeue(PQUEUE Q, int *val);#endifqueue.c⽂件代码:#include<stdio.h>#include<stdlib.h>#include"malloc.h"#include"queue.h"/***********************************************Function: Create a empty stack;************************************************/void CreateQueue(PQUEUE Q,int maxsize){Q->pBase=(int *)malloc(sizeof(int)*maxsize);if(NULL==Q->pBase){printf("Memory allocation failure");exit(-1); //退出程序}Q->front=0; //初始化參数Q->rear=0;Q->maxsize=maxsize;}/***********************************************Function: Print the stack element;************************************************/void TraverseQueue(PQUEUE Q){int i=Q->front;printf("队中的元素是:\n");while(i%Q->maxsize!=Q->rear){printf("%d ",Q->pBase[i]);i++;}printf("\n");}bool FullQueue(PQUEUE Q){if(Q->front==(Q->rear+1)%Q->maxsize) //推断循环链表是否满,留⼀个预留空间不⽤ return true;elsereturn false;}bool EmptyQueue(PQUEUE Q){if(Q->front==Q->rear) //推断是否为空return true;elsereturn false;}bool Enqueue(PQUEUE Q, int val){if(FullQueue(Q))return false;else{Q->pBase[Q->rear]=val;Q->rear=(Q->rear+1)%Q->maxsize;return true;}}bool Dequeue(PQUEUE Q, int *val){if(EmptyQueue(Q)){return false;}else{*val=Q->pBase[Q->front];Q->front=(Q->front+1)%Q->maxsize;return true;}}。
浙江大学城市学院实验报告课程名称数据结构基础实验项目名称实验八队列(循环队列)的表示和实现学生姓名专业班级学号实验成绩指导老师(签名)日期2014-11-27一.实验目的和要求1、掌握队列的存储结构及基本操作。
2、掌握循环队列的设置及循环队列的各种基本操作的实现。
3、通过具体的应用实例,进一步熟悉和掌握队列的实际应用。
二.实验内容1、建立头文件SeqQueue.h,定义顺序存储的循环队列存储结构,并编写循环队列的各种基本操作实现函数。
同时建立一个验证操作实现的主函数文件test3_2.cpp,编译并调试程序,直到正确运行。
2、选做:编写程序,实现舞伴问题。
假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队,跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴,若两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。
要求设计一个函数void partner(),模拟上述舞伴配对问题。
基本要求:1) 由键盘输入数据,每对数据包括姓名和性别;2) 输出结果包括配成舞伴的女士和男士的姓名,以及未配对者的队伍名称和队头者的姓名;3) 要求利用SeqQueue.h中已实现的顺序循环队列的基本操作函数来实现。
函数void partner() 添加到文件test3_2.cpp中,在主函数中进行调用测试。
3、填写实验报告,实验报告文件取名为report8.doc。
4、上传实验报告文件report8.doc、源程序文件test3_2.cpp及SeqQueue.h 到Ftp服务器上自己的文件夹下。
三. 函数的功能说明及算法思路抽象数据类型:ADT SET isData:一个队列Q,假定用标示符Queue表示队列的存储类型Operation:void InitQueue(Queue& Q)//初始化队列为空并带有动态存储空间分配int EmptyQueue(Queue Q)//判断队列是否为空,空返回1,否则返回0void EnQueue(Queue& Q , ElemType item )//向队列插入元素,若队列已满重新分配更大的存储空间ElemType OutQueue(Queue& Q)//从队列中删除元素并返回ElemType PeekQueue(Queue Q)//读取队首元素,不改变队列状态void ClearQueue(Queue &Q)//清除队列为空,并释放动态存储空间void partner(Queue a,Queue b)//实现解决舞伴问题end QUEUE存储结构:typedef char ElemType;struct Queue{ //动态分配ElemType *queue;int front,rear;//队头指针,队尾指针int MaxSize;//队列最大存储数};struct Dancer{ //存储舞者的姓名和性别char name;char sex;};解决舞伴问题分析:void partner(Queue a,Queue b)建立两个队列a和b,a放女生,b放男生。
根据队列队首出的原则,排在前面的人依次出列,直到有一队为空。
此时若有一队里面还有人未配对,则该队的对头就是等待下个舞曲的人。
四. 实验结果与分析男女人数相同:女队人数多:五. 心得体会了解队列性质,根据此才能编程【附录----源程序】test3_2.cpp:#include<stdio.h>#include<iostream.h>#include<stdlib.h>#include<string.h>#include "SeqQueue.h"int main(){Queue q;InitQueue(q);if(EmptyQueue (q))cout<<"队列为空"<<endl;elsecout<<"队列非空"<<endl;char date;cout<<"请输入元素(以#结尾)"<<endl;cin>>date;while(date!='#'){EnQueue (q,date);cin>>date;}cout<<"该队列的队头元素为:"<<PeekQueue(q)<<endl;cout<<"将输出队列数据"<<endl;while(!EmptyQueue(q))printf("%c ",OutQueue(q));cout<<endl;ClearQueue(q);cout<<"--------------实现舞伴问题------------------"<<endl;Queue a,b;InitQueue(a);InitQueue(b);partner(a,b);ClearQueue(a);ClearQueue(b);return 0;}SeqQueue.h:typedef char ElemType;struct Queue{ElemType *queue;int front,rear;//队头指针,队尾指针int MaxSize;//队列最大存储数};struct Dancer{char name;char sex;};void InitQueue(Queue& Q){//初始化队列为空并带有动态存储空间分配Q.MaxSize=10;Q.queue=new ElemType[Q.MaxSize];Q.rear=Q.front=0;}int EmptyQueue(Queue Q){//判断队列是否为空,空返回1,否则返回0return Q.front==Q.rear;}void EnQueue(Queue& Q , ElemType item ){//向队列插入元素,若队列已满重新分配更大的存储空间if((Q.rear+1)%Q.MaxSize==Q.front)//存储空间用完,申请两倍大小空间{int k=sizeof(ElemType);Q.queue=(ElemType*)realloc(Q.queue,2*Q.MaxSize*k);if(Q.rear!=Q.MaxSize-1){//把原队列的尾部内容向后移动MaxSize个位置for(int i=0;i<=Q.rear;i++)Q.queue[i+Q.MaxSize]=Q.queue[i];Q.rear+=Q.MaxSize;//指针也移动MaxSize个位置}Q.MaxSize=2*Q.MaxSize;}Q.rear=(Q.rear+1)%Q.MaxSize;Q.queue[Q.rear]=item;}ElemType OutQueue(Queue& Q){//从队列中删除元素并返回if(Q.front==Q.rear){cerr<<"队列已空,无法删除!"<<endl;exit(1);}//将front指向下一个元素并返回首元素Q.front=(Q.front+1)%Q.MaxSize;return Q.queue[Q.front];}ElemType PeekQueue(Queue Q){//读取队首元素,不改变队列状态if(Q.front==Q.rear){cerr<<"队列已空,无法读取!"<<endl;exit(1);}return Q.queue[(Q.front+1)%Q.MaxSize];}void ClearQueue(Queue &Q){//清除队列为空,并释放动态存储空间if(Q.queue!=NULL)free(Q.queue);Q.front=Q.rear=0;Q.queue=NULL;Q.MaxSize=0;}void partner(Queue a,Queue b){Dancer d; //存放舞者性别和年龄cout<<"请输入舞会上舞者的姓名和性别(a为女性,b为男性,并以#结束):"<<endl;cin>>>>d.sex;while(!='#' && d.sex!='#'){if(d.sex=='a') EnQueue(a,);else if(d.sex=='b') EnQueue(b,);else cout<<"性别输入错误!"<<endl;cin>>>>d.sex;}cout<<"男女配成队的舞伴是:"<<endl;while(!EmptyQueue(a) && !EmptyQueue(b))cout<<OutQueue(a)<<' '<<OutQueue(b)<<endl;if(!EmptyQueue(a)){cout<<"女队中有未配对者需等待下一轮舞曲。
"<<endl;cout<<OutQueue(a)<<"是下一轮第一个得到舞伴的人。
"<<endl;}if(!EmptyQueue(b)){cout<<"男队中有未配对者需等待下一轮舞曲。
"<<endl;cout<<OutQueue(b)<<"是下一轮第一个得到舞伴的人。
"<<endl;}}。