C语言线性表之队列算法二:循环队列
请首先看上文:C语言线性表之队列算法一:链式队列
四、循环队列
1. 我们上文中提到的静态队列就是用循环队列实现的,那为什么静态队列必须要用循环队列来实现呢?比如说一个队列可以容纳5个元素,此时队列满的情况下,我依次出队,等5个元素均出队完成后,再入队也入不进去,那前边已出队元素所占用的空间就白白学浪费了,比如下图所示,如果队头与队尾均指向最后的一个,那前边的空间怎么办呢?
2.初始化,队列的初始化分为以下的三步:
第一步:为数组(此处我们用数组来演示)分配相应的空间,但请注意,如果要分配的元素为n个,则请为数组分配n+1个空间,这样做是为了方便判断空及判断是否已满
第二步:设定队头指向第0个元素
第三步:设定队尾指向第0个元素
1 typedef struct Queue{ 2 int * pBase; 3 int front; 4 int rear; 5 } QUEUE; 6 //初始化 7 void init(QUEUE * pq){ 8 pq->pBase=(int *)malloc(sizeof(int)*6); 9 if(pq->pBase==NULL){ 10 printf("动态内存分配失败,程序退出!"); 11 exit(-1); 12 } 13 pq->front=0; 14 pq->rear=0; 15 }
3.入队,在入队时,我们只需要在Rear(队尾)入队即可,
首选判断是否已满(稍后说明);
第二步:在rear处插入元素(因为rear指向队列最后一个元素的下一个元素,所以是在rear处插入元素,而非在rear+1处插入;
第三步:将rear重新赋值,使其等于(rear+1)%6,其中6是数组的长度。
1 //入队 2 bool inQueue(QUEUE * pq,int val){ 3 if(isFull(pq)){ 4 printf("队列已满,无法入队!\n"); 5 return false; 6 } 7 pq->pBase[pq->rear]=val; 8 pq->rear=(pq->rear+1)%6; 9 printf("入队位置%d\n",pq->rear); 10 return true; 11 }
4.出队,出队时,需要在front端出队:
第一步:判断是否已空(稍后说明)
第二步:将front处的元素出队
第三步:将front重新赋值为(front+1)%6,其中6为数组的长度
1 //出队 2 void outQueue(QUEUE * pq){ 3 if(isEmpty(pq)){ 4 printf("队列已空,无法出队!\n"); 5 return ; 6 } 7 pq->front=(pq->front+1)%6; 8 }
5.判断是否为空,只有在rear与front相等时才会为空
1 //判空 2 bool isEmpty(QUEUE * pq){ 3 if(pq->front==pq->rear){ 4 printf("队列为空"); 5 return true; 6 } 7 return false; 8 }
6.判断是否已满,因为队列为循环队列,rear指向队列最后一个元素的下一个元素,所以只需要判断(rear+1)%6是否与front相等即可。
1 //判满 2 bool isFull(QUEUE * pq){ 3 if((pq->rear+1)%6==pq->front){ 4 return true; 5 } 6 return false; 7 }
7.main方法及结果截图
1 int main(int argc, char *argv[]) 2 { 3 QUEUE q; 4 init(&q); 5 outQueue(&q); 6 inQueue(&q,1); 7 inQueue(&q,2); 8 inQueue(&q,3); 9 inQueue(&q,4); 10 inQueue(&q,5); 11 showElements(&q); 12 inQueue(&q,6); 13 showElements(&q); 14 outQueue(&q); 15 showElements(&q); 16 return 0; 17 }
8.程序下载:点我