循环队列的操作

    队列和链表、堆栈一样都是一种线性结构。只不过队列的操作限定在两端,只能够在队头和队尾进行操作。它的特性是先进先出,在队尾进队头出。

队列的物理结构包括顺序存储结构和链式存储结构,也就是我们常说的顺序队列和链式队列。

    这里就说一下顺序队列,顺序存储结构要预先分配内存,最好能知道队列的最大长度,在顺序队列中当队头指针front和队尾指针rear指向同一位置的

时候,表示队列是空的如下图(a);当队尾指针指向末尾的时候,队列就满了如下图(d)。下面放一张图来说明顺序队列

 

     在图(a)中是顺序队列的初始状态,此时队头指针front和队尾指针rear指向同一位置;然后就可以直接向队中添加数据,入队后rear指向下一个位置,注意在添加

数据的时候front始终指向队头位置,添加后rear指向队尾元素的下一个位置,图(b)就是添加了数据后的队列;图(c)是出队后的状态,每次出队后,front就指向下一

个位置;在图(d)中,队尾指针rear已经指向了队列的末尾位置,没法再入队列了,如果再入队的话就会溢出,但实际上队头前面还有空的位置但又不能用,所以这样

就造成了空间的浪费,这是一种假溢出。为了解决这个问题,就引入了循环队列,循环队列,放上图片来说明

    第一个图是初始状态,然后开始入队,经过几次入队后,就到了第二个图,在此过程中队头指针front始终指向队头元素,队尾指针rear指向队尾元素的下一个位置,

这和上面的讲的一样。同样的,当队头指针front和队尾指针rear指向同一位置的时候,表示队列是空的,那在第三个图中就发现此时队列是满的,但是按照front=rear,

那么队列又是空的,这就矛盾了。所以这里就留一个位置不用,就是第二个图的样子,这时候通过 (Q->rear+1)%size==Q->front 这条语句来判断队列是否满了;假如

现在要用的队列长度是100,那就令size=101,多出来的一个不用,以便用 (Q->rear+1)%size==Q->front 这个条件来判断队列满了没有。

    讲的不太详细,多理解理解,拿笔去画画,试着演示一下,应该还是能明白的。下面就来展示一下循环队列的各种操作,包括初始化、入队、出队等,代码已经测

试过了,注释我写的也比较详细了。如有不对的地方,欢迎指出错误!

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<malloc.h>
  4 #include<stdlib.h>
  5 #define MAXSIZE 101
  6 using namespace std;
  7 typedef  struct
  8 {   int data[MAXSIZE];  //队列的大小
  9     int front;    //指向队头
 10     int rear;   //指向队尾元素的下一个位置,rear为非空
 11 }cQueue;    //循环队列
 12 
 13 cQueue* initQueue()   //初始化队列
 14 {
 15     cQueue* Q=(cQueue*)malloc(sizeof(cQueue));  //给队列开辟空间,成功返回首地址,失败返回NULL
 16     if(!Q )
 17     {
 18         printf("存储分配失败\n");
 19         exit(-1);
 20     }
 21     Q->front=0;
 22     Q->rear=0;    //空队列的话队头和队尾指向同一位置
 23     return Q;
 24 }
 25 int push(cQueue *Q,int e)  //入队成功返回1,入队失败返回0
 26 {
 27     if((Q->rear+1)%MAXSIZE==Q->front)  //队列已满    
 28         return 0;
 29     Q->data[Q->rear]=e;   //当前rear指向队尾元素的下一个位置,是空的,可直接入队
 30     Q->rear=(Q->rear+1)%MAXSIZE; //入队后再让rear指向下一个位置,下一个位置是空的,方便下次直接入队
 31     return 1;
 32 }
 33 int pop(cQueue *Q,int *e) //出队成功返回1,出队失败返回0
 34 {
 35     if(Q->rear==Q->front)   //空队列 
 36     {
 37         printf("队列为空\n");
 38         return 0;
 39     }
 40     *e=Q->data[Q->front];
 41     Q->front=(Q->front+1)%MAXSIZE;  //队头元素出队后,front指向下一个位置
 42     return 1;
 43 }
 44 int length(cQueue *Q)
 45 {
 46     return (Q->rear-Q->front+MAXSIZE)%MAXSIZE;
 47 }
 48 int isempty(cQueue *Q) //队列为空返回1,非空返回0
 49 {
 50     if(Q->front==Q->rear)
 51         return 1;
 52     else
 53         return 0;
 54 }
 55 void clear(cQueue *Q) //清空
 56 {
 57     Q->front=Q->rear;
 58 }
 59 void printQueue(cQueue *Q)
 60 {
 61     int i;
 62     i=Q->front;
 63     if(Q->front==Q->rear)
 64     {
 65         printf("队列是空的\n");
 66         exit(-1);
 67     }
 68     while(i!=Q->rear)
 69     {
 70         printf("%d ",Q->data[i]);
 71         i++;
 72         i=i%MAXSIZE;
 73     }
 74     printf("\n" );
 75 }
 76 int main()
 77 {
 78     int e;
 79     char ch=0;
 80     cQueue *Q;
 81     Q=initQueue();
 82     printf("输入待入队的元素:\n");
 83     do{
 84         scanf("%d",&e);
 85         push(Q,e);
 86     }while((ch=getchar())!='\n');
 87     printf("队中元素为:\n");
 88     printQueue(Q);
 89     printf("队列的长度为:%d\n",length(Q));
 90     for(int i=1;i<=5;i++)
 91     {
 92         pop(Q,&e);
 93         printf("第%d次出队的元素为:%d\n",i,e);
 94     }
 95     printf("pop后队列中的元素为:");
 96     printQueue(Q);
 97     printf("pop后队列的长度为:%d\n",length(Q));
 98     printf("结果为1表示队列为空,为0表示队列非空:%d\n",isempty(Q));
 99     clear(Q);
100     printf("结果为1表示队列为空,为0表示队列非空:%d\n",isempty(Q));
101     return 0;
102 }

结果如下:

 

2020-04-29      19:39:12

 

posted @ 2020-04-29 18:20  和运气碰碰  阅读(734)  评论(0编辑  收藏  举报