第二节 队列.docx
《第二节 队列.docx》由会员分享,可在线阅读,更多相关《第二节 队列.docx(10页珍藏版)》请在冰豆网上搜索。
第二节队列
第二节队列
一、队列的基本概念
1.队列的定义
只允许在表的一端进行插入,而在另一端进行删除。
队头(front)和队尾(rear):
允许删除的一端称为队头,允许插入的一端称为队尾。
2.队列的特征
运算受限的线性表。
队列的运算规则:
先进先出(FIFO)。
3.队列的基本运算
(1)队列初始化InitQueue(Q):
设置一个空队列Q。
(2)判队空:
EmptyQueue(Q):
若Q为空队列,则返回1,否则返回0。
(3)入队操作:
EnQueue(Q,x):
插入元素x为Q的新的队尾元素。
(4)出队操作:
OutQueue(Q):
删除Q的队首元素。
(5)取队头元素:
GetHead(Q):
返回Q的队首元素。
二、队列的顺序实现
1.思路
顺序存储的队列称为顺序队列,用一个一维数组存放当前队列中的元素,另设两个分别指示队首和队尾元素的变量,分别称为"队列首指针"和"队列尾指针"。
队首指针指向队列首元素的前一个单元。
2.顺序队列的定义
constintmaxsize=20;
typedefstructseqqueue
{DataTypedata[maxsize];
intfront,rear;
}SeqQue;
SeqQueSQ;
3.假溢出与循环队列
顺序队列操作的几个基本状态如下图:
空队列(初始化):
rear==0,且front==0
空队列的判断条件:
rear==front
队满的判断条件:
rear==M-1 (M为数组的元素个数)
队列中存在溢出现象:
假溢出(假上溢):
当rear==M-1时且rear-front≠M-1,有元素入队
下溢:
rear==front
假溢出(虚溢出)解决方法:
顺序结构下:
元素平移法;循环队列。
链式结构。
4.循环队列
(1)思路
是将连续的存储空间想象为一个首尾相接的圆环,并称这种存储为循环存储,存储在其中的队列称为循环队列(CircularQueue)。
为了解决难以区分队空队满,front所指的空间始终空闲。
(2)定义
constintmaxsize=20;
typedefstructcycqueue
{DataTypedata[maxsize];
intfront,rear;
}CycQue;
CycQueCQ;
(3)队空队满条件
队空条件:
CQ.rear==CQ.front
队满条件:
(CQ.rear+1)%maxsize==CQ.front
5.基本运算在循环队列上的实现算法
(1)队列初始化
voidInitQueue(CycQueCQ)
{CQ.front=0;
CQ.rear=0;
}
(2)判队空
intEmptyQueue(CycQueCQ)
{if(CQ.rear==CQ.front)return1; //队列为空,返回1
elsereturn0; //队列不空,返回0
}
(3)入队
intEnQueue(CycQueCQ,DataTypex)
{if((CQ.rear+1)%maxsize==CQ.front)
{error("队满");return0;} //队满不能入队
else{
CQ.rear=(CQ.rear+1)%maxsize;
CQ.data[CQ.rear]=x;
return1; //入队完成
}
}
(4)出队
intOutQueue(CyeQueCQ)
{if(EmptyQueue(CQ))
{Error("队空");return0;} //队空不能出队
else{
CQ.front=(CQ.front+1)%maxsize;
return1; //出队完成
}
}
(5)取队头元素
DataTypeGetHead(CyeQueCQ)
{if(EmptyQueue(CQ))
returnNULLData; //队空,返回空数据标志
else
returnCQ.data[(CQ.front+1%maxsize)];
}
三、队列的链接实现
1.思路
链式存储的队称为链队。
用带头结点的单链表来实现链队。
头指针指向链表的头结点,链表的头结点的next域指向队列首结点,尾指针指向队列尾结点。
2.链队列的定义
typedefstructLinkQueueNode
{DataTypedata;
structLinkQueueNode*next;
}LkQueNode; //链队列的结点类型
typedefstruct
{LkQueNode*front,*rear;
}LkQue; //将队头、队尾指针封装在一起
LkQueLQ;
3.基本运算在链队列上的实现算法
(1)队列初始化
voidInitQueue(LkQue*LQ)
{LkQueNode*temp;
temp=(LkQueNode*)malloc(sizeof(LkQueNode)); //分配队列头结点
temp->next=NULL;
LQ->front=temp;
LQ->rear=temp; //空队列,队头、队尾指针指向头结点
}
(2)判队空
intEmptyQueue(LkQue*LQ)
{if (LQ->rear==LQ->front) return1; //队列为空,返回1
elsereturn0; //队列不空,返回0
}
(3)入队
voidEnQueue(LkQue*LQ;DataTypex)
{LkQueNode*temp;
temp=(LkQueNode*)malloc(sizeof(LkQueNode)); //分配存储数据结点
temp->data=x; //存入数据
temp->next=NULL;
LQ->rear->next=temp; //新结点入队
LQ->rear=temp; //修改尾指针
}
(4)出队
intOutQueue(LkQue*LQ)
{LkQueNode*temp;
if(EmptyQueue(LQ)){error("队空");return0;}
else { temp=LQ->front->next; //找到队头
LQ->front->next=temp->next; //修改队头
free(temp);
if(LQ->front->next==NULL)
LQ->rear=LQ->front; //唯一的元素出队后,队尾要指向头结点
return1;}
}
(5)取队头元素
DataTypeGetHead(LkQueLQ)
{LkQueNode*temp;
if(EmptyQueue(LQ))
returnNULLData; //队空,返回空数据标志
else{temp=LQ.front->next;
returntemp->data;} //队非空,返回队首元素
}
四、队列的应用
银行办理业务时,需要排队等候,利用队列结构,可以模拟银行的业务办理流程。
(略)
五、考点提示
1.队列的基本概念
【例题·填空题】在队列结构中,允许插入的一端称为_______。
隐藏答案
【答案】队尾
【解析】允许删除的一端称为队头,允许插入的一端称为队尾。
2.队列的存储结构特点及改进,特别是循环的特点(如队空、队满条件)
【例题·填空题】若front和rear分别表示循环队列Q的头指针和尾指针,m0表示该队列的最大容量,则循环队列为空的条件是_________。
隐藏答案
【答案】Q.front=Q.rear
【解析】循环队列的队空条件是Q.front=Q.rear。
【例题·单选题】循环队列存储在数组元素A[0]至A[m]中,则入队时的操作为( )
A.rear=rear+1
B.rear=(rear+1)%(m-1)
C.rear=(rear+1)%m
D.rear=(rear+1)%(m+1)
隐藏答案
【答案】D
【解析】因为数组元素个数是m+1,所以应该选D。
3.队列的应用,主要在树、图的遍历等操作中用到队列结构。