顺序循环队列的基本原理
为防止顺序队列的假溢出问题,把顺序队列所使用的存储空间构造成一个逻辑上首尾相连的循环队列。当rear和front达到maxSize - 1后,再前进一个位置就自动到0。利用高级程序设计语言int数据类型的求模(或称取余、取模)运算(%)来实现。
顺序循环队列各状态的判断问题
front:队头指针;rear:队尾指针;maxSize - 1:队列的最大容量
- front:指向队列的第一个元素,也就是说queue[front]就是队列的第一个元素。front的初始值为0。
- rear:只想队列的最后一个元素的后一个位置。因为希望空出一个空间作为约定。rear的初始值为0。
- 队列满的条件:(rear + 1) % maxSize == front
- 队列空的条件:rear == front
- 队列中的有效的数据个数:(rear + maxSize - front) % maxSize
- 队尾指针加1(注意取模):rear = (rear + 1) % maxSize
- 队头指针加1(注意取模):front = (front + 1) % maxSize
顺序循环队列的实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//队列的最大容量:4
#define maxSize 5
typedef struct{
int queue[maxSize];
int rear; //队尾
int front; //对头
}Struct_ArrayQueue; //队列结构体
//初始化队列
void QueueInitiate(Struct_ArrayQueue *Q){
memset(Q->queue, 0x00, sizeof(Q->queue)); //初始化队列
Q->front = 0; //初始化对头 ,指向队列头部的前一个位置
Q->rear = 0; //初始化队尾 ,指向队列尾部的具体数据
}
//判断队列满
int isFull(Struct_ArrayQueue Q){
if(((Q.rear + 1) % maxSize) == Q.front)
return 1; //队列满返回1
else
return 0; //队列没满返回0
}
//判断队列是否空
int isEmpty(Struct_ArrayQueue Q){
if(Q.rear == Q.front)
return 1; //队列空返回1
else
return 0; //队列不空返回0
}
//添加数据到队列
int addQueue(Struct_ArrayQueue *Q, int n) {
if(((Q->rear + 1) % maxSize) == Q->front) { //判断队列是否满,满了就无法添加数据
printf("队列已满无法添加数据\n");
return 0;
}
//直接添加数据
Q->queue[Q->rear] = n;
//rear后移,这里必须考虑取模
Q->rear = (Q->rear + 1) % maxSize;
return 1;
}
//数据出队列, 取数据
int getQueue(Struct_ArrayQueue *Q, int *d){
//判断队列是否空
if(Q->rear == Q->front){
printf("队列为空,无数据出队列\n");
return 0;
}
//front是指向队列的第一个元素
*d = Q->queue[Q->front]; //将数据传给d,让d带回main函数
Q->queue[Q->front] = 0; //取出后赋值为0
Q->front = (Q->front + 1) % maxSize; //front后移 ,考虑取模
return 1;
}
//显示队列所有数据
void showQueue(Struct_ArrayQueue Q){
int i;
//判断是否为空
if(isEmpty(Q))
printf("队列为空,没有数据\n");
else{
//从front开始遍历,遍历多少个元素
for(i = Q.front; i < Q.front + size(Q); i++){
printf("arr[%d] = %d\n", i % maxSize, Q.queue[i % maxSize]);
}
}
}
//求出当前队列的有效个数
int size(Struct_ArrayQueue Q){
return (Q.rear + maxSize - Q.front) % maxSize;
}
//显示对头数据, 注意不是取出
int headQueue(Struct_ArrayQueue Q, int *d){
//判断是否为空
if(isEmpty(Q)){
printf("队列为空,无对头数据可显示\n");
return 0;
}
*d = Q.queue[Q.front];
return 1;
}
int main(int argc, char *argv[]) {
//测试数组模拟环形队列
Struct_ArrayQueue Q;
int loop = 1, value, res;
char key;
//初始化队列
QueueInitiate(&Q);
while(loop) {
printf("s(show): 显示队列\n");
printf("e(exit): 退出程序\n");
printf("a(add): 添加数据到队列\n");
printf("g(get): 从队列里面取数据\n");
printf("h(head): 查看队列头的数据\n");
key = getchar();
switch(key){
case 's': //显示队列
showQueue(Q);
break;
case 'a': // 添加数据到队列
scanf("%d", &value);
addQueue(&Q, value);
break;
case 'g': //从队列里面取数据
if(getQueue(&Q, &res)){
printf("取出的数据是:%d\n", res);
}
break;
case 'h': //查看队列头的数据
if(headQueue(Q, &res)){
printf("当前对列头的数据是:%d\n", res);
}
break;
case 'e':
loop = 0;
break;
default:
break;
}
getchar(); //吸收回车,避免前面的目录两次输出
}
printf("程序退出\n");
return 0;
}
本篇参考