如果说可以用循环队列解决队列的虚假满的状态,那么什么是虚假满状态?
假设当前顺序队列分配的最大空间是6,当队尾指针从5下标指向6下标时(6下标实际不存在),说明此时队列已满,然而依然可以进行出队的操作,顺序队不能像顺序栈那样进行存储再分配扩大数组空间,所以队列的实际可用空间并未占满。
循环队列就是将顺序队列构造成为一个环状的队列空间,如图:
注意:
此时当指针front=指针rear时,无法判断队列空间是满还是空,有两种解决思路:
1.另设一个标志位区分队列空间是满还是空;
2.少用一个空间,约定以“队列头指针在队列尾指针的下一位置”作为队列满的状态标志。
来吧!举个栗子吧,如图:
【情况1】
初始化,队头指针front,队尾指针rear都指向0下标;
当存入数据元素1后,队尾指针rear从0下标指向1下标;
当存入数据元素2后,队尾指针rear从1下标指向2下标;
当存入数据元素3后,队尾指针rear从2下标指向3下标;
当存入数据元素4后,队尾指针rear从3下标指向4下标;
…
当存入数据元素8后,队尾指针rear从7下标指向0下标;(队列已满)
如何判断队头指针front与队尾指针rear重合时,队列是空还是满呢?我们假如用flag来标记队头指针front与队尾指针rear的重合状态,于是规定当flag=0时:队列为空;当flag=1时,队列为满。
【情况2】
我们把7下标的空间空出不存放数据,当数据元素7进为6下标的空间后,队尾指针rear就指向了为7下标的空间(此时7下标空间是空的),理论上8个空间只用了7个空间,但在逻辑上我们规定此时队列已满。当rear+1后,队头指针front与队尾指针rear重合,说明此时队列空间逻辑已满,我们先将队头指针所指空间的元素出队,队头指针前移指向1下标,此时再将元素进下标为7的空间,队尾指针rear前移(指向0下标),当rear+1后,队头指针front与队尾指针rear又重合,说明此时队列空间逻辑又已满,依次循环往复,出队—>队头指针front前移——>后面入队——>队尾指针rear前移(判断条件是rear+1后,队头指针front与队尾指针rear是否重合,不重合则可继续入队)。
但是,计算机是没有环状的存储空间的,依然是以线性存储的方式,那计算机如何判断什么时候队尾指针再次与队头指针重合呢?
—————OK!那就是:进行模运算—————
具体模运算是怎么实现的,文字显得苍白无力,还是那句话,把代码跑起来,慢慢体会!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| #include <stdio.h> #include <malloc.h> #include <assert.h>
#define MAXSIZE 8 typedef int ElmeType;
typedef struct Queue { ElmeType *base; int front; int rear; }Queue;
void InitQueue(Queue *Q) { Q->base=(ElmeType *)malloc(sizeof(ElmeType)*MAXSIZE); assert(Q->base!=NULL); Q->front=Q->rear=0; }
void EnQueue(Queue *Q,ElmeType x) {
if((Q->rear+1)%MAXSIZE==Q->front) return; Q->base[Q->rear]=x; Q->rear=(Q->rear+1)%MAXSIZE; }
void ShowQueue(Queue *Q) { printf("顺序队列中存放的元素:"); for(int i=Q->front;i!=Q->rear;) { printf("%d ",Q->base[i]); i=(i+1)%MAXSIZE; } printf("\n"); }
void DeQueue(Queue *Q) {
if(Q->front==Q->rear) return; Q->front=(Q->front+1)%MAXSIZE; }
void GetHead(Queue *Q,ElmeType *v) {
if(Q->front==Q->rear) return; *v=Q->base[Q->front]; }
int Length(Queue *Q) { return (Q->rear - Q->front); }
void ClearQueue(Queue *Q) { Q->front=Q->rear=0; }
void DestroyQueue(Queue *Q) { free(Q->base); Q->base=NULL; }
void main() { Queue Q; ElmeType e; InitQueue(&Q); printf("将1,2,3,4,5,6,7,8依次入队\n"); for(int i=1;i<=8;++i) { EnQueue(&Q,i); } ShowQueue(&Q); printf("顺序队的长度为:%d\n",Length(&Q)); printf("\n"); printf("进行出队\n"); DeQueue(&Q); ShowQueue(&Q); GetHead(&Q,&e); printf("队头元素为:%d\n",e); printf("\n"); printf("将元素10入队\n"); EnQueue(&Q,10); ShowQueue(&Q); printf("\n"); printf("进行出队\n"); DeQueue(&Q); ShowQueue(&Q); GetHead(&Q,&e); printf("队头元素为:%d\n",e); printf("\n"); printf("将元素20入队\n"); EnQueue(&Q,20); ShowQueue(&Q); printf("\n"); ClearQueue(&Q); DestroyQueue(&Q); }
|
运行结果: