概念
循环顺序队列即顺序存储的队列,是为了避免 "假溢出"而利用%运算符将队列首尾相接连成一个环状的队列。
循环顺序队列中,当队尾指针到达数组末端时,如果队头指针指向的元素不是空,那么队尾指针就会从数组的开始继续移动;如果队头指针指向的元素是空,那么队头指针就会从数组的末尾开始移动。循环顺序队列可以有效地利用数组空间,避免因为假溢出而造成空间的浪费。
一、循环顺序队列算法
循环顺序队列通常使用一个一维数组实现,其基本操作包括入队、出队、判断队列是否为空、判断队列是否已满等。
以下是循环顺序队列的基本算法:
1、初始化:设定一个数组用于存储队列元素,并设定两个指针,一个指向队头元素,一个指向队尾元素的下一个位置。
2、入队操作:将元素添加到队尾,并将队尾指针后移一位。如果队尾指针已经到达数组末端,则将其循环移动到数组开头。
3、出队操作:将队头元素出队,并将队头指针后移一位。如果队头指针已经到达数组末端,则将其循环移动到数组开头。
4、判断队列是否为空:检查队头指针和队尾指针是否重合。如果重合,则队列为空。
5、判断队列是否已满:检查队尾指针和队头指针的差值是否等于数组长度减一,如果等于,则队列已满。
以上是循环顺序队列的基本算法。在实际应用中,可以根据需要进行修改和扩展。
二、算法的实现
- 1.循环队列初始化
-
int init(CirclesQueue *Q) { Q->front = Q->rear = 0; return 0; }
- 2.入栈
-
int enqueue(CirclesQueue *Q, DataType x) { if (isfull(Q)) { printf("队列已满!100001\n"); return 100001; } Q->rear = (Q->rear + 1) % MAXSIZE; Q->data[Q->rear] = x; return 0; }
- 3.出队
-
int dequeue(CirclesQueue *Q, DataType *x) { if (isempty(Q)) { printf("队列为空!100002\n"); return 100002; } Q->front = (Q->front + 1) % MAXSIZE; *x = Q->data[Q->front]; return 0; }
- 4.队列是否已满
-
int isfull(CirclesQueue *Q) { return (Q->rear + 1) % MAXSIZE == Q->front ? 1 : 0; }
- 5.队列是否为空
-
int isempty(CirclesQueue *Q) { return (Q->front == Q->rear) ? 1 : 0; }
- 6.队列长度
-
int getLength(CirclesQueue *Q, DataType *length) { *length = (Q->rear - Q->front + MAXSIZE) % MAXSIZE; return 0; }
- 7.取队首元素
-
int getHead(CirclesQueue *Q, DataType *x) { if (isempty(Q)) { printf("队列为空!100002\n"); return 100002; } *x = Q->data[(Q->front + 1) % MAXSIZE]; return 0; }
- 8.输出队列元素
-
void printQueue(CirclesQueue *Q) { if (isempty(Q)) { printf("队列为空!\n"); return; } int front = (Q->front + 1) % MAXSIZE; while (front != (Q->rear + 1) % MAXSIZE) { printf("%d", Q->data[front]); front = (front + 1) % MAXSIZE; }
三、完整Demo
1.CirclesQueue.h
#define MAXSIZE 100
typedef int DataType;
typedef struct
{
DataType data[MAXSIZE];
int front;
int rear;
}CirclesQueue;
/*循环队列初始化*/
int init(CirclesQueue *Q);
/*入队*/
int enqueue(CirclesQueue *Q, DataType x);
/*队满*/
int isfull(CirclesQueue *Q);
/*出队*/
int dequeue(CirclesQueue *Q, DataType *);
/*队空*/
int isempty(CirclesQueue *Q);
// 输出队列内容
void printQueue(CirclesQueue *Q);
// 获取队列长度
int getLength(CirclesQueue *Q);
// 获取队首元素
DataType getFront(CirclesQueue* Q);
2.CirclesQueue.c
#include <stdio.h>
#include "CirclesQueue.h"
/*循环队列初始化*/
int init(CirclesQueue *Q)
{
Q->front = Q->rear = 0;
return 0;
}
/*入队*/
int enqueue(CirclesQueue *Q, DataType x)
{
if(isfull(Q))
{
printf("队列已满!100001\n");
return 100001;
}
Q->rear = (Q->rear+1) % MAXSIZE;
Q->data[Q->rear] = x;
return 0;
}
/*队满*/
int isfull(CirclesQueue *Q)
{
return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
}
/*出队*/
int dequeue(CirclesQueue *Q, DataType *x)
{
if(isempty(Q))
{
printf("队列为空!100002\n");
return 100002;
}
Q->front = (Q->front+1) % MAXSIZE;
*x = Q->data[Q->front];
return 0;
}
/*队空*/
int isempty(CirclesQueue *Q)
{
return (Q->front == Q->rear) ? 1 : 0;
}
// 输出队列内容
void printQueue(CirclesQueue *Q) {
int i;
if (isempty(Q)) {
printf("Queue is empty.\n");
return;
}
i = (Q -> front) %MAXSIZE;
do{
printf(" %d",Q -> data[(i + 1 % MAXSIZE)]);
i = (i+1) %MAXSIZE;
}while(i != Q -> rear);
}
// 获取队列长度
int getLength(CirclesQueue *Q) {
return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}
// 获取队首元素
DataType getFront(CirclesQueue* Q) {
int i;
i = (Q -> front) %MAXSIZE;
return Q -> data[(i + 1 % MAXSIZE)];
}
3.main.c
#include <stdio.h>
#include "CirclesQueue.h"
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
CirclesQueue Q;
DataType x;
int cmd;
char yn;
int result;
char welcome[] = "Start Operation";
int i = 0;
int m = 0;
int n = 0;
for(i=0;i<strlen(welcome);i++)
{
printf("%c",welcome[i]);
for(m=0;m<10000;m++)
for(n=0;n<1000;n++)
{
;
}
}
printf("\n\n\n");
do
{
printf("-----------Demo演示-----------\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(" 9. 帮助\n");
printf(" 0. 退出\n");
printf(" 请选择(0~6):");
scanf("%d",&cmd);
switch(cmd)
{
case 1:
init(&Q);
printf("队列已初始化!\n");
break;
case 2:
printf("请输入要入队的元素x=");
scanf("%d", &x);
if(!enqueue(&Q,x))
{
printf("元素x=%d已入队\n", x);
}
break;
case 3:
printf("确定要出队(出队会将删除对首元素, y or n, n)?");
getchar();
scanf("%c", &yn);
if(yn == 'y' || yn == 'Y')
{
if(!dequeue(&Q,&x))
{
printf("队首元素【%d】已出队!\n", x);
}
}
break;
case 4:
if(isempty(&Q)) printf("队列为空!\n");
else printf("队列不为空!\n");
break;
case 5:
if(isfull(&Q)) printf("队列已满!\n");
else printf("队列还没有满!\n");
break;
case 6:
printf("队列的长度:%d\n",getLength(&Q));
break;
case 7:
printf("队列首元素: %d\n", getFront(&Q));
break;
case 8:
printf("输出队列:");
printQueue(&Q);
printf("\n");
break;
case 9:
printf("本程序演示到此结束,感谢观看。\n");
break;
}
}while(cmd!=0);
return 0;
}
运行截图:
总结
- 循环顺序队列的基本概念:了解什么是循环顺序队列,掌握其特点和使用场景。
- 循环顺序队列的原理:理解循环顺序队列的原理,包括如何实现循环移动、如何进行入队和出队操作等。
- 循环顺序队列的应用:学习循环顺序队列的应用场景,如广度优先搜索、深度优先搜索等。