循环队列的优势
相比普通的队列,能够有效节省内存的使用,无需再次分配内存
循环队列的实现源码
#include"stdio.h"
#include"stdlib.h"
//这是一个静态队列的例程
#define MAXSIZE 10 //队列的最大容量
typedef char ElemType; //定义一个队列元素类型,这种编程思路很好,程序有扩展空间
//声明一个有关循环队列的数据块,注意每个元素的意义!
struct Queue
{
ElemType *base;//数据类型头指针
int front; //队头(front)进行队列元素删除操作的数组指针索引,很巧妙!
int rear; //队尾(rear)进行队列元素插入操作的数组指针索引,很巧妙!
};
//创建队列或曰初始化队列
void Queue_Iinit(Queue * q)
{
// q= new Queue;
q->base=(ElemType *)malloc(MAXSIZE*sizeof(ElemType));//
if(!q->base)
{
printf("内存分配失败!\n");
exit(1);
}
q->front=q->rear=0;
//这一步很重要!将队头和队尾指针索引q->front,q->rea都赋值为0,即同时指向数组第一个元素
}
//入队操作,入队从队尾rear处开始
void InsertQueue(Queue * q,ElemType e)
{
if((q->rear+1)%MAXSIZE==q->front)//先判断队列是否已满,因为入队从队尾rear处开始,所以先判断rear指针索引
/*
表达式(q->rear+1)%MAXSIZE也叫取模运算,该表达式能确保(q->rear+1)%MAXSIZE的结果小于MAXSIZE!
这样可以确保数组指针不越界。为什么要rear加1呢?腾出一个数据的空闲空间。
这种算法很技巧!
*/
{
printf("队列已满!\n");
return;
}
q->base[q->rear]=e;//
q->rear=((q->rear+1)%MAXSIZE);//这一步既实现了指针前移同时还实现了指针不越界!技巧!
}
//出队操作,出队是从队头front处开始
void DeleteQueue(Queue * q,ElemType *e)
{
if(q->front==q->rear)//已空,说明队列元素已经删除完毕
{
printf("老大,队列已空!\n");
return;
}
// *(e++)=q->base[q->front];//完成此步还不够!还需要指针索引移位!注意赋值方法!
*e=q->base[q->front];//完成此步还不够!还需要指针索引移位!注意赋值方法!
q->front=(q->front+1)%MAXSIZE; //指针指向下一个空闲空间,确保不越界
}
//判断队列是否为空
bool EmptyQueue(Queue * q)
{
if(q->front==q->rear) //判断是否为空
{
printf("队列已空!\n");
return true;
}
else
return false;
}
//判断队列是否为满
bool FullQueue(Queue * q)
{
if((q->rear+1)%MAXSIZE==q->front) //判断循环链表是否满,留一个预留空间不用
{
printf("队列已满!\n");
return true;
}
else
return false;
}
/***********************************************
输出每一个元素
************************************************/
void TraverseQueue(Queue * q)
{
int i=q->front;
printf("队中的元素是:\n");
while( (i%MAXSIZE)!=q->rear ) //注意,这里没有加1,打印每一个元素
{
printf("%c\n ",q->base[i]);
i++;
}
printf("\n");
}
void main()
{
Queue q;
char c;
Queue_Iinit(&q);
printf("请输入循环队列元素,以#作为结束符\n");
scanf("%c",&c);//注意!本句表示一次输入一个字符
InsertQueue(&q,c);
/*
注意:比如输入“1110010#”再按下回车键,字符串“1110010#”就以一次一个字符的顺序输入到PC键盘缓冲区即入栈;
出栈时是以“后进先出”的顺序出栈,刚好最后入栈的字符就是二进制的最低位。对于栈的操作一定要注意入栈出栈顺序
*/
while(c!='#')
{
scanf("%c",&c);//这里为什么还要此句呢?因为scanf()一次只能输入一个字符,所以必须循环输入
InsertQueue(&q,c);
}
getchar();//改变键盘输入缓存指针,即将回车键读出来,这样可以避免“\r”字符(回车键)输出
TraverseQueue(&q);
printf("开始出队命令!\n");
while(1)
{
DeleteQueue(&q,&c);
printf("出队:%c\n ",c);
if( EmptyQueue( &q))
break;
}
}