数据结构:队列的若干问题总结

队列的定义:队列( Queue)简称队,只允许一端进行插入,另一端进行删除。前者可以叫“入队”或者“进队”,后者可以叫“出队”或者“离队”。队列和平时在排队过程中的逻辑是一样的,如果要入队,必然插入到线性结构的后方,如果要离队,肯定是从线性结构的前方离开的。这一原则我们叫FIFO(First In First Out)。队列的存储结构:1:队列的顺序存储所谓顺序存储其实就和顺序表的思维差不多,定义一个线性结构,只能表头前出队,只能表头后进队。以下是数据结构:#define Maxsize
摘要由CSDN通过智能技术生成

队列的定义:

队列( Queue)简称队,只允许一端进行插入,另一端进行删除。前者可以叫“入队”或者“进队”,后者可以叫“出队”或者“离队”。队列和平时在排队过程中的逻辑是一样的,如果要入队,必然插入到线性结构的后方,如果要离队,肯定是从线性结构的前方离开的。这一原则我们叫FIFO(First In First Out)。

队列的存储结构:

1:队列的顺序存储


所谓顺序存储其实就和顺序表的思维差不多,定义一个线性结构,只能表头前出队,只能表头后进队。以下是数据结构:

#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) return 1;
    return 0;
}

//第三种模式:使用标识性变量tag来区分队头指针和队尾指针相等时的状态
//如果tag==1,那么说明相等是因为队满所造成,如果tag==0,则相
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值