赞
踩
队列(quque)简称队,只允许在表的一端输入,在表的另一端删除(操作受限制的线性表),
把进行插入的一段叫做队尾(表尾),把进入删除的一端叫做队首或队头(表头)。
队列最主要的特点:先进先出,FIFO(first in first out)
队列有其实有三种:顺序队列、 循环队列、链式队列
为了避免顺序队列中出现的假溢出现象,我们只需要把数组的前后端连接起来,形成一个环形数组,在逻辑上把这个环称为环形队列或者循环队列。
下面是循环队列的实现过程:
假设栈的元素个数最大不超过正整数MAXSIZE,所以元素具有同一数据类型(ElemType),用下来方式来声明循环队列的类型SQQueue:
- #define MAXSIZE 10 //队列的最大容量
-
- typedef int ElemType; //队列中元素类型
-
- typedef struct
- {
- ElemType data[MAXSIZE];//存储值
- int front;//存储队头元素前一个单元的下标
- int rear;//存储队尾元素的下标
- }SQQueue;
对于循环队列来说,有以下四个非常重要的要素:
1.队空条件:SQ->front == SQ->rear
2.队满条件:SQ->rear+1)%MAXSIZE == SQ->front
3.进队操作:
SQ->rear = (SQ->rear + 1) % MAXSIZE;
SQ->data[SQ->rear] = e;
先将 SQ->rear = (SQ->rear + 1) % MAXSIZE,再将元素e放在rear指向的位置
4.出队操作:
SQ->front = (SQ->front+1) % MAXSIZE;
*e = SQ->data[SQ->front];
先将 SQ->front = (SQ->front+1) % MAXSIZE,再将取出front指向的位置上的元 素并存放于e中
1)队列初始化
构造一个空的队列SQ,将front和rear指针都指向-1,代码如下:
- void InitQueue(SQQueue* SQ)
- {
- SQ->front = SQ->rear = -1;
-
- }
2)判断队列是否为空
注:为了区分空和满,任意时候都预留1个单元出来x的下一个:(x+1)%MAXSIZE
循环队列中,判断队列是否为空,只需要判断SQ->front == SQ->rear的条件成立即可,代码如下:
- //判断队列为空
-
- void InitQueue(SQQueue* SQ)
- {
- SQ->front = SQ->rear = -1;
-
- }
3)判断队列是否为满
循环队列中,判断队列是否为满,只需要判断(SQ->rear+1)%MAXSIZE == SQ->front的条件成立即可,
特别注意,循环队列中的特殊情况,初始状态下SQ->front == -1,当执行进队操作SQ->rear == MAXSIZE - 2时队列已满,需要将这一特殊情况考虑,代码如下:
- int IsFUll(SQQueue* SQ) //判断队列是否为满
- {
- //尾指针+1追上队头指针,标志队列已经满了
- if(((SQ->rear+1)%MAXSIZE == SQ->front)||(SQ->rear==MAXSIZE-2&&SQ->front==-1))
- {
- return 1;
- }
- return 0; //队不满
- }
4)入队
在队列不满条件下先将rear+1,再将元素e放在rear指向的位置,因此该操作需要先判断操作合法性,若队列未满,执行相关操作,否则提示并返回0,这里可以调用IsFull(SQQueue* SQ)来判断,代码如下:
-
- int EnterQueue(SQQueue* SQ,ElemType e)
- {
- if (IsFUll(SQ)) // (SQ->rear + 1)%MAXSIZE == SQ->front
- {
- printf("队满,不能进队。\n");
- return 0;
- }
- SQ->rear = (SQ->rear + 1) % MAXSIZE;
- SQ->data[SQ->rear] = e;
- }
5)出队
这里需要先判断循环队列是否为空,若为空,提示并返回0,若不空则执行相关操作, 先将 SQ->front = (SQ->front+1) % MAXSIZE,再将取出front指向的位置上的元 素并存放于e中,这里可以调用IsEmpty(SQQueue* SQ)来判断,代码如下:
- int DeleteQueue(SQQueue* SQ,ElemType* e)
- {
- if (IsEmpty(SQ))
- {
- printf("队空,不能出队!\n");
- return 0;
- }
- SQ->front = (SQ->front+1) % MAXSIZE;
- *e = SQ->data[SQ->front];
- }
6)求队列长度
代码如下:
- int lenghtSQQueue(SQQueue* SQ)
- {
- int len;
- len = 0;
- len = (SQ->rear-SQ->front+MAXSIZE)%MAXSIZE;
- return len;
- }
7)打印队列中的元素
从队首到队尾,代码如下:
- //打印队列中的与元素
-
- void DispSQQueue(SQQueue* SQ)
- {
- if (IsEmpty(SQ))
- {
- printf("队空!");
- }
- int i;
- i = SQ->front+1;
- printf("队列元素为:");
- while(i <= SQ->rear)
- {
-
- printf("%d ",SQ->data[i]);
- i++;
- }
- }

下面是入队、出栈和返回队列长度以及打印出队列元素的操作:
- int main()
- {
- SQQueue SQ;
- ElemType e;
- InitQueue(&SQ);
-
- //入队
- EnterQueue(&SQ,1);
- EnterQueue(&SQ,2);
- EnterQueue(&SQ,3);
- EnterQueue(&SQ,4);
- EnterQueue(&SQ,5);
- EnterQueue(&SQ,6);
- EnterQueue(&SQ,7);
- EnterQueue(&SQ,8);
- EnterQueue(&SQ,9);
- EnterQueue(&SQ,10);
-
- //打印队列元素
- DispSQQueue(&SQ);
- printf("\n");
- printf("队列长度为:%d\n",lenghtSQQueue(&SQ));
- //出队
- DeleteQueue(&SQ,&e);
- printf("出队元素为:%d\n",e);
- DeleteQueue(&SQ,&e);
- printf("出队元素为:%d\n",e);
-
- //打印队列元素
- DispSQQueue(&SQ);
- printf("\n");
-
- EnterQueue(&SQ,8);
- EnterQueue(&SQ,9);
- //打印队列元素
- DispSQQueue(&SQ);
- printf("\n");
- EnterQueue(&SQ,10);
-
-
- printf("队列长度为:%d\n",lenghtSQQueue(&SQ));
- return 1;
- }

测试结果如下:
当元素10进栈时,队满提示,并返回队列元素,在将队首元素出栈两次,返回队列元素,再将元素8,9进队,再返回队列元素,此时再将元素10进队时提示队满,返回队列长度,自此,循环队列构造完成。
最后再附上完整代码:
- #include <stdio.h>
-
- #define MAXSIZE 10
-
- typedef int ElemType;
-
- typedef struct
- {
- ElemType data[MAXSIZE];//存储值
- int front;//存储队头元素前一个单元的下标
- int rear;//存储队尾元素的下标
- }SQQueue;
-
- /*
- 初始化:front=-1;rear=-1;
- 为了区分空和满,任意时候都预留1个单元出来
- x的下一个:(x+1)%MAXSIZE
-
- 空:front==rear
- 满:(rear+1)%MAXSIZE==front
- 进队:
- rear=(rear+1)%MAXSIZE;
- data[rear]=e;
- 出队:
- front=(front+1)%MAXSIZE;
- *e=data[front];
-
- 长度:
- (rear-front+MAXSIZE)%MAXSIZE
-
- */
-
- /*
- 空:q->front==NULL && q->rear==NULL
- */
-
- void InitQueue(SQQueue* SQ)
- {
- SQ->front = SQ->rear = -1;
-
- }
-
- int IsEmpty(SQQueue* SQ) //判断队列是否为空
- {
- if (SQ->front == SQ->rear)
- {
- return 1; //队空
- }
- return 0;
- }
-
- int IsFUll(SQQueue* SQ) //判断队列是否为满
- {
- //尾指针+1追上队头指针,标志队列已经满了
- if(((SQ->rear+1)%MAXSIZE == SQ->front)||(SQ->rear==MAXSIZE-2&&SQ->front==-1))
- {
- return 1;
- }
- return 0; //队不满
- }
-
- int EnterQueue(SQQueue* SQ,ElemType e)
- {
- if (IsFUll(SQ)) // (SQ->rear + 1)%MAXSIZE == SQ->front
- {
- printf("队满,不能进队。\n");
- return 0;
- }
- SQ->rear = (SQ->rear + 1) % MAXSIZE;
- SQ->data[SQ->rear] = e;
- }
-
- int DeleteQueue(SQQueue* SQ,ElemType* e)
- {
- if (IsEmpty(SQ))
- {
- printf("队空,不能出队!\n");
- return 0;
- }
- SQ->front = (SQ->front+1) % MAXSIZE;
- *e = SQ->data[SQ->front];
- }
-
- int lenghtSQQueue(SQQueue* SQ)
- {
- int len;
- len = 0;
- len = (SQ->rear-SQ->front+MAXSIZE)%MAXSIZE;
- return len;
- }
-
- void DispSQQueue(SQQueue* SQ)
- {
- int index;
- int i;
-
- i = 1;
- index=(SQ->front+1)%MAXSIZE;
- printf("队列元素为:");
- while(i <= lenghtSQQueue(SQ))
- {
- printf("%d ",SQ->data[index]);
- index=(index+1)%MAXSIZE;
-
- i++;
- }
- }
-
- int main()
- {
- SQQueue SQ;
- ElemType e;
- InitQueue(&SQ);
-
- //入队
- EnterQueue(&SQ,1);
- EnterQueue(&SQ,2);
- EnterQueue(&SQ,3);
- EnterQueue(&SQ,4);
- EnterQueue(&SQ,5);
- EnterQueue(&SQ,6);
- EnterQueue(&SQ,7);
- EnterQueue(&SQ,8);
- EnterQueue(&SQ,9);
- EnterQueue(&SQ,10);
-
- //打印队列元素
- DispSQQueue(&SQ);
- printf("\n");
- printf("队列长度为:%d\n",lenghtSQQueue(&SQ));
- //出队
- DeleteQueue(&SQ,&e);
- printf("出队元素为:%d\n",e);
- DeleteQueue(&SQ,&e);
- printf("出队元素为:%d\n",e);
-
- //打印队列元素
- DispSQQueue(&SQ);
- printf("\n");
-
- EnterQueue(&SQ,8);
- EnterQueue(&SQ,9);
- //打印队列元素
- DispSQQueue(&SQ);
- printf("\n");
- EnterQueue(&SQ,10);
-
-
- printf("队列长度为:%d\n",lenghtSQQueue(&SQ));
- return 1;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。