(图解)循环队列的三种判断队空、队满操作(附带源码和插入删除操作等一些基本操作)

这篇具有很好参考价值的文章主要介绍了(图解)循环队列的三种判断队空、队满操作(附带源码和插入删除操作等一些基本操作)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

 

一、普通的顺序存储队列

二、循环队列

(1)少用一个元素空间

i、初始化队列操作:

iii、入队操作:

iv、出队操作:

(2)设置flag标志

i、初始化队列操作:

ii、判断队空操作:

iii、入队操作:

iv、出队操作:

(3)设置length存储队列元素的个数

i、初始化队列操作:

ii、判断队空操作:

iii、入队操作:

iv、出队操作:

 (4) 总结

三、循环队列测试程序

(1)少用一个元素空间

(2)设置flag标志

(3)设置length存储队列元素的个数

四、拓展

(1)思路

(2)修改代码

队空和队满条件没有改变。

 i、初始化操作:

ii、判断队列为空操作:

iii、入队操作:

iv、出队操作:

(3)测试程序


一、普通的顺序存储队列

在介绍循环队列三种判断队空、队满操作之前,先解释下为啥会用循环队列。

队列一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一段称为队尾,允许删除的一段称为队头

咱们看一下普通的顺序存储队列:

普通的顺序储存队列的存储结构为:

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue
{
    DataType data[MAXSIZE];  // 存储队列的数据空间
    int front;   // 队头指针
    int rear;    // 队尾指针   
}SeqQueue;    

如图所示:

循环队列判断队空和队满,数据结构,数据结构,c语言

         front、rear分别指向队头,也就是数组索引为0的地方,此时队列为空(即rear == front), 

现在将0、1、2、3、4依次入队(队尾指针rear一直向后移,队头指针front不动)。

如图所示:

循环队列判断队空和队满,数据结构,数据结构,c语言

         0、1、2、3、4入队后,rear指向数组的后面,此时队满(即rear == MAXSIZE),然后再将0、1、2、3、4出队,出队后变为 队尾指针和队头指针都指向数组后面(即 rear == front),但如果现在 5 想入队却又入不了,应为 rear的值已经超过数组的最大索引,像这种数组有位置但却无法插入的这种现象叫做“假溢出”。

如图所示:

循环队列判断队空和队满,数据结构,数据结构,c语言

         但如果咱们想rear在数组索引为0处就好。有这个想法的同学很不错,这就引出了循环队列

二、循环队列

        像上面想的那样,咱们只要把队尾和队头连,那个rear不就指向数组索引为0的地方,这就是循环队列。而怎样实现呢?只需将 入队后的rear 和 出队后的front 同 MAXSIZE取余即可。例如上面的队满时,rear = 5,对MAXSIZE取余后,即 rear = rear % MAXSIZE = 0;符合我们的想法。

rear = (rear + 1) % MAXSIZE; // 入队后取余
front = (front + 1) % MAXSIZE; // 出队后取余

循环队列:队列头尾相接的顺序存储结构就是循环队列。

如图所示

循环队列判断队空和队满,数据结构,数据结构,c语言

 此时循环队列为空(rear == front)。然后将0、1、2、3、4入队,此时的rear会指向数组索引为0的地方,不会像上面普通队列那样指到数组外。

循环队列判断队空和队满,数据结构,数据结构,c语言

 然后将0、1出队,rear指针不动,front指向2处。

循环队列判断队空和队满,数据结构,数据结构,c语言

 此时 5 入队,如果是普通队列的话,此时入队便失败(由于rear指向了数组外),但循环队列不会,此时rear指向 0 处,而之前 0 处的项已经出队,故可入队。

循环队列判断队空和队满,数据结构,数据结构,c语言

        此时衍生一个问题,就是咱们之前队满时,有rear == front,但之前队空时 ,也有rear == front。那当 rear == front 时,是队空还是队满呢?这是不是很有歧义,所以咱们就要来解决这个问题。(即使判断队空和队满的条件不同,消除歧义)。

解决这个问题的三种方法:

  1. 少用一个元素的空间;
  2. 设置一个flag,来区别队列的 “空” 和 “满” ;
  3. 设置一个变量。统计队列中的元素数量。

(1)少用一个元素空间

        当队满时,rear 和 front相差一个元素,此时的 rear 不等于 front,也就区分了队空和队满的条件(即 rear == front 为队空,而非队满)。

循环队列判断队空和队满,数据结构,数据结构,c语言

 此时 (rear + 1) % MAXSIZE == front 为队队满,rear == front 为队空。

队空的判断条件

q->rear == q->front

队满的判断条件

(q->rear + 1) % MAXSIZE == q->front;

队列的存储结构:

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue
{
    DataType data[MAXSIZE];  // 存储队列的数据空间
    int front;   // 队头指针
    int rear;    // 队尾指针   
}SeqQueue;    

i、初始化队列操作:

        利用malloc()函数分配队列的存储结构,再将 front = rear = 0;此时队列为空。

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue)); // 队列的存储结构
	q->front = q->rear = 0; // 初始化rear和front,队列为空
	printf("循环队列已经创建完毕\n");
	return q;
}

ii、判断队空操作:

        利用队空判断条件 rear == front;成立队列为空,不成立队列不为空。

bool QueueEmpty(SeqQueue* q)
{
	if (q->rear == q->front)  // 判断队空
		return true;
	return false;
}

iii、入队操作:

        首先利用队满条件判断队列是否为满,队满则退出入队函数,不为满着进行入队操作,并将 rear 利用 rear =(rear+1) % MAXSIZE 进行更新。

bool EnQueue(SeqQueue* q, DataType x)
{
	if ((q->rear+1) % MAXSIZE == q->front) // 判断队满
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear] = x; // 入队
	q->rear = (q->rear + 1) % MAXSIZE; // 更新rear
	return true;
}

iv、出队操作:

        利用队空条件判断队列是否为空,队列为空不能进行出队操作。队不为空时,进行出队操作,并将front = (front + 1) % MAXSIZE 进行更新。

DataType DeQueue(SeqQueue* q)
{
	DataType x; // 出队元素的值
	if (q->rear == q->front)  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	x = q->data[q->front]; // 出队
	q->front = (q->front + 1) % MAXSIZE; // 更新front
	return x;
}

(2)设置flag标志

        当设置flag标志时,就不需要空出一个元素的位置。队满时,flag对应一个值,队空时,flag对应一个与队满时flag的值不同的值(即队空和队满的flag值不一样),所以当 front == rear 时,依靠 flag值就可以区分队空队满。

:flag标志可以自选,符合上面的flag条件即可。(队满和队空的flag值不同)。

队列的存储结构:

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue{
	DataType data[MAXSIZE];
	int front;
	int rear;
	bool flag;
}SeqQueue;

当 rear = front 且 flag = flase 时队空. 

循环队列判断队空和队满,数据结构,数据结构,c语言

 当 rear = front 且 flag = true时,队列为满。

 循环队列判断队空和队满,数据结构,数据结构,c语言

 队空判断条件:

(q->front == q->rear) && !(q->flag)

队满判断条件:

(q->front == q->rear) && q->flag

i、初始化队列操作:

        利用malloc()函数创建队列,初始化 rear = front = 0,并将 flag 设置为队空标志(flag = false)。

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue)); // 分配队列的内存
	q->flag = false; // 设置队空标志
	q->front = q->rear = 0; // 初始化 rear和 front
	printf("循环队列已经创建完毕\n");
	return q;
}

ii、判断队空操作:

        利用队空判断条件进行判断,成立则队空,不成立则队不为空。

bool QueueEmpty(SeqQueue* q)
{
	if ((q->front == q->rear) && !(q->flag))  // 判断队空
		return true;
	return false;
}

iii、入队操作:

        首先判断利用队满条件判断是否可以入队,可以入队,然后再进行入队操作,并更新rear,入队后,需要判断 rear 是否等于 front,(即入队后要判断队是否为满)队满设置flag为队满的的flag值。(这就是和最开始的循环队列的区别,因为最开始的循环队列,当入队后rear = front,没设置区分队空和队满的标志,在退出入队函数后,就区分不了队空、队满,此时 rear = front)。

bool EnQueue(SeqQueue* q, DataType x)
{
	if ((q->front == q->rear) && q->flag) // 判断队满
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear++] = x; // 入队
	q->rear %= MAXSIZE; // 更新rear
	if (q->rear == q->front) // 判断入队后,队是否为满,满则设置队满标志flag
		q->flag = true; // 队满
	return true;
}

iv、出队操作:

        首先利用队空判断条件判断队列是否为空,可以出队,再执行出队操作,并更新front,出队后,需要判断 rear 是否等于 front,(即出队后要判断队是否为空)队空设置flag为队空的的flag值。(这就是和最开始的循环队列的区别,因为最开始的循环队列,当出队后rear = front,没设置区分队空和队满的标志,在退出出队函数后,就区分不了队空、队满,此时 rear = front)。

DataType DeQueue(SeqQueue* q)
{
	DataType x; // 出队的元素的值
	if ((q->front == q->rear) && !(q->flag))  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	x = q->data[q->front++]; // 出队
	q->front %= MAXSIZE; // 更新front
	if (q->front == q->rear) // 判断出队后队列是否为空,设置flag标志
		q->flag = false; // 队空
	return x;
}

(3)设置length存储队列元素的个数

        利用length来存储队列的元素个数(即队列的长度),不需要为了判断队满、队空牺牲一个元素的空间,同时利用 length 这个变量,判断队空、队满很简单,(即length = 0,队空;length = MAXSIZE,队满),不需要利用到 rear 和 front 来判断队空、队满。

队列的存储结构:

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue {
	DataType data[MAXSIZE];
	int front;
	int rear;
	int length;
}SeqQueue;

当 length = 0时,队空。

循环队列判断队空和队满,数据结构,数据结构,c语言

 当 length = MAXSIZE时,队满。

循环队列判断队空和队满,数据结构,数据结构,c语言

 队空判断条件:

q->length == 0

队满判断条件:

q->length == MAXSIZE

i、初始化队列操作:

        利用malloc()函数分配队列的空间,并初始化 rear 和 front,初始化 length = 0,为队空的标志。

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue)); // 分配队列空间
	q->length = 0;   // 初始化length,队列为空
	q->rear = q->front = 0; // 初始化rear 和 front
	printf("循环队列已经创建完毕\n");
	return q;
}

ii、判断队空操作:

        直接利用 length = 0 来判断队列是否为空。

bool QueueEmpty(SeqQueue* q)
{
	if (q->length == 0)  // 判断队空
		return true;
	return false;
}

iii、入队操作:

        首先利用队满条件判断队列是否已满,未满则进行入队操作,并更新rear,队列长度加一(length++)。

bool EnQueue(SeqQueue* q, DataType x)
{
	if (q->length == MAXSIZE) // 判断队满
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear++] = x; // 入队
	q->rear %= MAXSIZE; // 更新rear
	q->length++; // 队列长度加一
	return true;
}

iv、出队操作:

        利用队列为空条件判断队列是否为空,空就不进行出队操作。不为空时,出队,更新front,队列长度减一(length--)。

DataType DeQueue(SeqQueue* q)
{
	DataType x; // 出队元素的值
	if (q->length == 0)  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	q->data[q->front++] = x; // 出队
	q->front %= MAXSIZE; // 更新front
	q->length--; // 队列的长度减一
	return x;
}

 (4) 总结

        总体来说,使用 length 来保存队列的元素个数(队列长度)的方法,是最简单的。而带有flag标志区分队满、对空的方法,则较难点。牺牲一个元素的方法在二者之间,可以根据自身的情况来选用这三种方法的一种。

三、循环队列测试程序

在所有队列使用之前,均要初始化队列。

(1)少用一个元素空间

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue{
	DataType data[MAXSIZE];
	int front;
	int rear;
}SeqQueue;

SeqQueue* InitQueue();
bool QueueEmpty(SeqQueue* q);
bool EnQueue(SeqQueue* q, DataType x);
DataType DeQueue(SeqQueue* q);
void ShowQueue(SeqQueue* q);
int ShowMeanu();

int main(void)
{
	int choice;
	SeqQueue* queue;
	while (true)
	{
		int choice;
		choice = ShowMeanu();
		switch (choice)
		{
			case 0:	exit(0);
				break;
			case 1: queue = InitQueue();
				break;
			case 2: {
				int x;
				printf("请输入要入队的值:");
				scanf("%d", &x);
				EnQueue(queue, x);
			}
				  break;
			case 3: DeQueue(queue);
				break;
			case 4: {
				bool statue = QueueEmpty(queue);
				if (statue)
					printf("队列为空\n");
				else
					printf("队列不为空\n");
			}
				  break;
			case 5: ShowQueue(queue);
				break;

			default: printf("请输入恰当的测试功能!!!\n");
		}
	}
	return 0;
}

int ShowMeanu()
{
	int choice;
	printf("\n欢迎来到循环队列测试程序!!!!!\n");
	printf("有以下功能可提供测试\n");
	printf("1.创建循环队列        2.入队\n");
	printf("3.出队               4.判断队空\n");
	printf("5.队列显示\n");
	printf("0.退出程序\n");
	printf("你需要测试的功能是:");
	scanf("%d", &choice);
	return choice;
}

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue));
	q->front = q->rear = 0;
	printf("循环队列已经创建完毕\n");
	return q;
}

bool QueueEmpty(SeqQueue* q)
{
	if (q->rear == q->front)  // 判断队空
		return true;
	return false;
}

bool EnQueue(SeqQueue* q, DataType x)
{
	if ((q->rear+1) % MAXSIZE == q->front)
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear] = x;
	q->rear = (q->rear + 1) % MAXSIZE;
	return true;
}

DataType DeQueue(SeqQueue* q)
{
	DataType x;
	if (q->rear == q->front)  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	x = q->data[q->front];
	q->front = (q->front + 1) % MAXSIZE;
	return x;
}

void ShowQueue(SeqQueue* q)
{
	int front, rear;
	front = q->front;
	rear = q->rear;
	if (rear == front)
    {
		printf("队列为空!!!\n");
        return;
    }
	while (rear != front)
		printf("%d\n", q->data[front++]);
	return;
}

(2)设置flag标志

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue{
	DataType data[MAXSIZE];
	int front;
	int rear;
	bool flag;
}SeqQueue;

SeqQueue* InitQueue();
bool QueueEmpty(SeqQueue* q);
bool EnQueue(SeqQueue* q, DataType x);
DataType DeQueue(SeqQueue* q);
void ShowQueue(SeqQueue* q);
int ShowMeanu();

int main(void)
{
	int choice;
	SeqQueue* queue;
	while (true)
	{
		int choice;
		choice = ShowMeanu();
		switch (choice)
		{
			case 0:	exit(0);
				break;
			case 1: queue = InitQueue();
				break;
			case 2: {
				int x;
				printf("请输入要入队的值:");
				scanf("%d", &x);
				EnQueue(queue, x);
			}
				  break;
			case 3: DeQueue(queue);
				break;
			case 4: {
				bool statue = QueueEmpty(queue);
				if (statue)
					printf("队列为空\n");
				else
					printf("队列不为空\n");
			}
				  break;
			case 5: ShowQueue(queue);
				break;

			default: printf("请输入恰当的测试功能!!!\n");
		}
	}
	return 0;
}

int ShowMeanu()
{
	int choice;
	printf("\n欢迎来到循环队列测试程序!!!!!\n");
	printf("有以下功能可提供测试\n");
	printf("1.创建循环队列        2.入队\n");
	printf("3.出队               4.判断队空\n");
	printf("5.队列显示\n");
	printf("0.退出程序\n");
	printf("你需要测试的功能是:");
	scanf("%d", &choice);
	return choice;
}

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue));
	q->flag = false;
	q->front = q->rear = 0;
	printf("循环队列已经创建完毕\n");
	return q;
}

bool QueueEmpty(SeqQueue* q)
{
	if ((q->front == q->rear) && !(q->flag))  // 判断队空
		return true;
	return false;
}

bool EnQueue(SeqQueue* q, DataType x)
{
	if ((q->front == q->rear) && q->flag)
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear] = x;
	++(q->rear);
	q->rear %= MAXSIZE;
	if (q->rear == q->front) // 设置队列已满
		q->flag = true;
	return true;
}

DataType DeQueue(SeqQueue* q)
{
	DataType x;
	if ((q->front == q->rear) && !(q->flag))  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	x = q->data[q->front++];
	q->front %= MAXSIZE;
	if (q->front == q->rear) // 设置队列为空
		q->flag = false;
	return x;
}

void ShowQueue(SeqQueue* q)
{
	int front, rear;
	front = q->front;
	rear = q->rear;
	if ((front == rear) && !(q->flag))
    {
	    printf("队列为空\n");
        return;
    }
	/*while (front != rear) // 循环输出队列元素
	{
		printf("%d\n", q->data[front++]);
		front %= MAXSIZE;
	}  // 忽略了队满 rear == front*/

	// 先输出一个元素,便可解决上面此种情况
	printf("%d\n", q->data[front++]);
	while (front != rear) // 循环输出队列元素
	{
		printf("%d\n", q->data[front++]);
		front %= MAXSIZE;
	}
	return;
}

(3)设置length存储队列元素的个数

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue {
	DataType data[MAXSIZE];
	int front;
	int rear;
	int length;
}SeqQueue;

SeqQueue* InitQueue();
bool QueueEmpty(SeqQueue* q);
bool EnQueue(SeqQueue* q, DataType x);
DataType DeQueue(SeqQueue* q);
void ShowQueue(SeqQueue* q);
int ShowMeanu();

int main(void)
{
	int choice;
	SeqQueue* queue;
	while (true)
	{
		int choice;
		choice = ShowMeanu();
		switch (choice)
		{
		case 0:	exit(0);
			break;
		case 1: queue = InitQueue();
			break;
		case 2: {
			int x;
			printf("请输入要入队的值:");
			scanf("%d", &x);
			EnQueue(queue, x);
		}
			  break;
		case 3: DeQueue(queue);
			break;
		case 4: {
			bool statue = QueueEmpty(queue);
			if (statue)
				printf("队列为空\n");
			else
				printf("队列不为空\n");
		}
			  break;
		case 5: ShowQueue(queue);
			break;

		default: printf("请输入恰当的测试功能!!!\n");
		}
	}
	return 0;
}

int ShowMeanu()
{
	int choice;
	printf("\n欢迎来到循环队列测试程序!!!!!\n");
	printf("有以下功能可提供测试\n");
	printf("1.创建循环队列        2.入队\n");
	printf("3.出队               4.判断队空\n");
	printf("5.队列显示\n");
	printf("0.退出程序\n");
	printf("你需要测试的功能是:");
	scanf("%d", &choice);
	return choice;
}

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue));
	q->length = 0;
	q->rear = q->front = 0;
	printf("循环队列已经创建完毕\n");
	return q;
}

bool QueueEmpty(SeqQueue* q)
{
	if (q->length == 0)  // 判断队空
		return true;
	return false;
}

bool EnQueue(SeqQueue* q, DataType x)
{
	if (q->length == MAXSIZE)
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear++] = x;
	q->rear %= MAXSIZE;
	q->length++;
	return true;
}

DataType DeQueue(SeqQueue* q)
{
	DataType x;
	if (q->length == 0)  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	q->data[q->front++] = x;
	q->front %= MAXSIZE;
	q->length--;
	return x;
}

void ShowQueue(SeqQueue* q)
{
	int front = q->front;
	int length = q->length; // 存储队列长度
	if (length == 0)
	{
		printf("队列为空!!!\n");
		return;
	}
	while (length != 0)
	{
		printf("%d\n", q->data[front++]);
		front %= MAXSIZE;
		length--;
	}
	return;
}

四、拓展

        当上面的方法三(即利用length来保存队列的元素个数),少了一个指针,你是否还能进行入队、出队的操作。这里我用少了一个队头指针(front)来做演示。

(1)思路

        少了一个front队头指针,我们的出队就变的好像不知所措,我们一般想如果它能用length 和 rear 表示该多好,而这也正是解决此题的方法,我们需要找出 rear、front 和 length 这三者之间的关系。

       length 表示列表长度,那 首先猜想length = rear - front 是不是可以推出 front = rear - length 呢?看下图:

循环队列判断队空和队满,数据结构,数据结构,c语言

 此时length = 2, rear = 4,。front = rear - length = 2好像可以,但再看下图:

循环队列判断队空和队满,数据结构,数据结构,c语言此时 length = 3,rear = 0。front = rear - length = -3那就不行了,故 front  rear - length

        咱们想对上面第二个图(即front = -3),rear 加上空的位置个数是不是就是front,对的,它就是front,那空的位置个数等于数组的最大元素的个数减去队列的长度(MAXSIZE - length),即 front = (rear + MAXSIZE - length). 但又看第一个图:

循环队列判断队空和队满,数据结构,数据结构,c语言

 此时 front 好像不需要MAXSIZE就可得出(front = rear - length);那现在要解决的问题就是,要在需要MAXSIZE就要有,不需要则无,因为 MAXSIZE 对其本身求模为 0,故在把上公式对MAXSIZE求模,就相当于MAXSIZE没有,故公式改进为 front = (rear + MAXSIZE - length) % MASIZE.符合两个图,那就推出了length 、rear、front三者之间的关系(即  front = (rear + MAXSIZE - length) % MASIZE)。然后利用这个关系就可以修改之前那个源码了。

(2)修改代码

队列的存储结构:

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue{
	DataType data[MAXSIZE];
	int rear;
	int length; // 少了front指针
}SeqQueue;

队空和队满条件没有改变。

队空条件:

q->length == 0

队满条件:

q->length == MAXSIZE

 i、初始化操作:

        利用malloc()函数分配队列的空间,初始化length和rear。

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue));
	q->length = 0; // 初始化length
	q->rear = 0; // 初始化
	printf("循环队列已经创建完毕\n");
	return q;
}

ii、判断队列为空操作:

        利用length == 0.

bool QueueEmpty(SeqQueue* q)
{
	if (q->length == 0)  // 判断队空
		return true;
	return false;
}

iii、入队操作:

        入队操作和上面的没变——利用队满条件判断队列是否已满,未满则进行入队操作,并更新rear,队列长度加一(length++)。

bool EnQueue(SeqQueue* q, DataType x)
{
	if (q->length == MAXSIZE) // 判断队满
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear++] = x; // 入队
	q->rear %= MAXSIZE;    // 更新rear
	q->length++;    // 队列长度加一
	return true;
}

iv、出队操作:

        出队操作改变了,这里要声明一个局部变量,充当 front 队头指针,利用关系front = (rear + MAXSIZE - length) % MASIZE求出队头的位置,再进行出队操作并更新length。

DataType DeQueue(SeqQueue* q)
{
	DataType x;
	int front; // 局部变量,相当于队头指针
	if (q->length == 0)  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	front = (MAXSIZE - q->length + q->rear) % MAXSIZE; // 求出队头指针位置
	x = q->data[front]; // 出队
	q->length--;    // 队列长度减一
	return x;
}

        如果是去掉队尾指针rear,则利用等式 rear = (front + length) % MAXSIZE 求出rear,其等式过程是怎样形成的,与上面类似(去掉front队头指针),请自行思考。

(3)测试程序

在使用队列之前,请对队列初始化。文章来源地址https://www.toymoban.com/news/detail-796286.html

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define MAXSIZE 5

typedef int DataType;

typedef struct Queue{
	DataType data[MAXSIZE];
	int rear;
	int length;
}SeqQueue;

SeqQueue* InitQueue();
bool QueueEmpty(SeqQueue* q);
bool EnQueue(SeqQueue* q, DataType x);
DataType DeQueue(SeqQueue* q);
void ShowQueue(SeqQueue* q);
int ShowMeanu();

int main(void)
{
	int choice;
	SeqQueue* queue;
	while (true)
	{
		int choice;
		choice = ShowMeanu();
		switch (choice)
		{
		case 0:	exit(0);
			break;
		case 1: queue = InitQueue();
			break;
		case 2: {
			int x;
			printf("请输入要入队的值:");
			scanf("%d", &x);
			EnQueue(queue, x);
		}
			  break;
		case 3: DeQueue(queue);
			break;
		case 4: {
			bool statue = QueueEmpty(queue);
			if (statue)
				printf("队列为空\n");
			else
				printf("队列不为空\n");
		}
			  break;
		case 5: ShowQueue(queue);
			break;

		default: printf("请输入恰当的测试功能!!!\n");
		}
	}
	return 0;
}

int ShowMeanu()
{
	int choice;
	printf("\n欢迎来到循环队列测试程序!!!!!\n");
	printf("有以下功能可提供测试\n");
	printf("1.创建循环队列        2.入队\n");
	printf("3.出队               4.判断队空\n");
	printf("5.队列显示\n");
	printf("0.退出程序\n");
	printf("你需要测试的功能是:");
	scanf("%d", &choice);
	return choice;
}

SeqQueue* InitQueue()
{
	SeqQueue* q;
	q = (SeqQueue*)malloc(sizeof(SeqQueue));
	q->length = 0;
	q->rear = 0;
	printf("循环队列已经创建完毕\n");
	return q;
}

bool QueueEmpty(SeqQueue* q)
{
	if (q->length == 0)  // 判断队空
		return true;
	return false;
}

bool EnQueue(SeqQueue* q, DataType x)
{
	if (q->length == MAXSIZE)
	{
		printf("循环队列已满!\n");
		return false;
	}
	q->data[q->rear++] = x;
	q->rear %= MAXSIZE;
	q->length++;
	return true;
}

DataType DeQueue(SeqQueue* q)
{
	DataType x;
	int front;
	if (q->length == 0)  // 判断队空
	{
		printf("队列为空!不能进行删除操作\n");
		return -1;
	}
	front = (MAXSIZE - q->length + q->rear) % MAXSIZE;
	x = q->data[front];
	q->length--;
	return x;
}

void ShowQueue(SeqQueue* q)
{
	int front;
	int length = q->length; // 存储队列长度
	if (length == 0)
	{
		printf("队列为空!!!\n");
		return;
	}
	while (length != 0)
	{
		front = (MAXSIZE - length + q->rear) % MAXSIZE;
		printf("%d", q->data[front]);
		length--;
	}
	return;
}

到了这里,关于(图解)循环队列的三种判断队空、队满操作(附带源码和插入删除操作等一些基本操作)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言判断素数的三种方法 判断素数(质数)

    题目: 方法一:在2到n-1之间任取一个数,如果n能被整除则不是素数,否则就是素数 代码示例如下: 代码运行结果如下: 方法二:在2到n/2之间任取一个数,如果n能被整除则不是素数,否则就是素数  代码示例如下: 代码运行结果如下: 方法三:在2到sqrt(n)之间任取一个数,如

    2024年02月02日
    浏览(89)
  • 使用java判断质数的三种方法

    方法一:质数只能被1和它本身整除  方法二:一个数总能写成“n = a * b”的形式,a和b之间一定有一个数不大于n/2  方法三:每一个整数都可以看做由两个数相乘得到,且每个乘数不大于原整数的平方根  

    2024年02月13日
    浏览(41)
  • java中判断对象类型的三种方法

    instanceof instanceof 是 Java 中的一个,用于判断一个对象是否是指定类型或其子类型的实例。它的使用格式为: 其中, 对象 是待判断的对象, 类型 是要判断的类型。 instanceof 的返回值是一个布尔值,如果对象是指定类型或其子类型的实例,则返回 true ,否则返回

    2024年02月03日
    浏览(33)
  • 【C语言】判断字符类型的三种方法

    🦄 个人主页 :修修修也 🎏 所属专栏 :C语言 ⚙️ 操作环境 : Visual Studio 2022 目录 一.字符的类型分类 1.ASCII的定义:  2.ASCII的产生原因是: 3.ASCII的内容: 二.字符类型判断相关库函数 1.isdigit(),用于判断字符是否为数字。 2. isalpha(),用于判断字符是否为字母。 3. isalnum(),用

    2024年02月06日
    浏览(34)
  • C语言素数(质数)判断的三种方法

    本文介绍了判断素数的3种方法,从素数的概念分析,确定找到素数的几个必要条件,设计思路,并将代码进行优化。此外,还使用自定义函数的形式将同样的思路进行实现。 素数,就是仅能被自身和1整除的数字。 首先我们可以提取出判断素数的三个基本条件: 素数是整数

    2024年02月04日
    浏览(32)
  • C语言if判断语句的三种用法

    一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。 C 语言中 if 语句的语法: 如果布尔表达式为 true,则 if 语句内的代码块将被执行。如果布尔表达式为 false,则 if 语句结束后的第一组代码(闭括号后)将被执行。 C 语言把任何非零和非空的值假定为 true,把零或 n

    2024年02月06日
    浏览(51)
  • java跳出for循环的三种常见方法

    这篇文章主要给大家介绍了关于java跳出for循环的三种常见方法,需要的朋友可以参考下 一、 break语句:使用break语句可以结束整个for循环的执行: 当 i 等于5时, break 语句会将控制流程跳出 for 循环从而停止后续代码的执行。 二、 return语句:如果你想要跳出当前方法并且停止

    2024年04月23日
    浏览(25)
  • RabbitMQ 简单实现创建队列的三种方式

    //1. 手动创建,需在RabbitMQ中手动创建myQueue1 队列,否则报错 @RabbitListener(queues = “myQueue1”) public void process1(String message){ log.info(“MqReceiver1: {}”, message); } //2. 自动创建队列 @RabbitListener(queuesToDeclare = @Queue(“myQueue2”)) public void process2(String message){ log.info(“MqReceiver2: {}”, messa

    2024年02月15日
    浏览(29)
  • Python 判断列表里是否有重复元素的三种方法

    一、用 set 方法去重后与原列表长度比较 二、用 append 的方式把原列表中的元素添加到一个新列表,确保新列表里不存在重复的元素,然后比较两个列表 三、用 fromkeys 的方法创建一个字典,因为字典的键会自动去重,所以可以比较字典和原列表的长度,跟方法一很像

    2024年02月11日
    浏览(41)
  • Python中退出While循环的三种方法举例

    在Python学习及编程应用中,常会使用while循环,对while循环条件设置不当可能导致进入死循环,本文将举例说明三种退出while循环的方法。 利用input函数使得输入值传递到while之后的条件判断句中,使while后的结果为False。 举例: 程序1: 运行结果举例 使用input将输入的值,通过

    2024年02月09日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包