赞
踩
队列( Queue)简称队,只允许一端进行插入,另一端进行删除。前者可以叫“入队”或者“进队”,后者可以叫“出队”或者“离队”。队列和平时在排队过程中的逻辑是一样的,如果要入队,必然插入到线性结构的后方,如果要离队,肯定是从线性结构的前方离开的。这一原则我们叫FIFO(First In First Out)。
所谓顺序存储其实就和顺序表的思维差不多,定义一个线性结构,只能表头前出队,只能表头后进队。以下是数据结构:
- #define Maxsize 50
- typedef int ElemType;
- typedef struct{
- ElemType data[Maxsize]; //存放队列元素
- int front,rear; //队头指针和队尾指针
- }SqQueue;
队空条件:Q.front==Q.rear==0。
入队操作:队不满,先送值到队尾元素,再将队尾指针+1。
出队操作:队不空时,先取头元素值,再将队尾值-1。
当然,队空的条件是头指针和尾指针相等,现在的问题是怎么判断队满呢?以下分情况讨论一下:
可以看到,如果只是让Q.rear==Maxsize是不能解决问题的。因为在(d)情况下,前面的元素都出队了,但Q.rear==Maxsize且整个队列还有空闲空间,这不能说明队满,这并不是真正的队列溢出。这种情况被称为“假溢出”。为了解决这个问题,可以考虑将该队列模式首尾相接,改为一个循环队列来解决此问题。
2.循环队列
在该思路下,我们可以将存储队列的表从逻辑上视为一个环,这样的队列就成为循环队列。即上图(d)情况下,我们可以让rear指针在最后存满之后,还能在front指针前面存储相关的数据。
初始时:Q.front==Q.rear==0。
队首指针进1:Q.front=(Q.front+1)%Maxsize 。
队尾指针进1:Q.rear=(Q.rear+1)%Maxsize。
此时还面临一个问题,那就是如何判断队满。如果只是简单地使用Q.front==Q.rear==0,就会出现下列情况:
可以看到,队满时会出现这种情况,但队空时也会出现这种情况。所以必须要想办法区别开两种情况。
我们有以下解决办法:
①:最普遍的做法是,入队时少用一个单元,约定“队头指针在队尾指针的下一个位置作为对满的标志”。
这样,我们就可以看到队满的条件可以这样判断:
队满条件:(Q.rear+1)%Maxsize=Q.front
队空条件仍:Q.front==Q.rear
队列中元素的个数:(Q.rear+Maxsize-Q.front)%Maxsize
②:还有一个做法是,增加一个数据成员size。这样队空的条件为Q.size==0;队满的条件就可以变为Q.size==Maxsize。这两种情况就有Q.front==Q.rear。
③:还有一个方法是加入数据成员tag。当tag==0时,若因删除导致Q.front==Q.rear,则为队空;tag==1时,若因插入导致Q.front=Q.rear,则表示队满。
初始化:
- void InitQueue(SqQueue Q){
- Q->front=Q->rear==0; //初始化队列首尾指针
- }
队列判空:
- int IsEmpty(SqQueue Q){
- //如果是空,则首尾指针相等,返回1,如果是非空,返回0.
-
- if(Q->front==Q->rear) return 1;
- else
- return 0;
- }
队列判满:
- //判满返回1,判空返回0
- //第一种模式:循环队列空出一个位置的方式判满
- int IsFull(SqQueue Q){
- if((Q->rear+1)%Maxsize==Q->front) return 1;
- return 0;
- }
-
-
- //第二种模式,使用一个变量来计量队列内元素数量
- int IsFull(SqQueue Q){
- if(Q->size==Maxsize) ret
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。