数据结构历年考研真题对应知识点(队列)

目录

3.2队列

3.2.2队列的顺序存储结构

【特定条件下循环队列队头/队尾指针的初值(2011)】

【特定条件下循环队列队空/队满的判断条件(2014)】

3.2.3队列的链式存储结构

【根据需求分析队列适合的存储结构(2019)】

【链式队列队空的判断(2019)】

【链式队列出队/入队操作的基本过程(2019)】 

3.2.4双端队列

【双端队列出队/入队操作模拟(2010、2021)】


3.2队列

3.2.2队列的顺序存储结构

特定条件下循环队列队头/队尾指针的初值(2011)】

  • 初始时:Q.front=Q.rear=0。
  • 队首指针进1:Q.front=(Q.front+1)%Maxsize。
  • 队尾指针进1:Q.rear=(Q.rear+1)%Maxsize。
  • 队列长度:(Q.rear+MaxSize-Q.front)%MaxSize。

特定条件下循环队列队空/队满的判断条件(2014)】

那么,循环队列队空和队满的判断条件是什么呢?显然,队空的条件是Q.front==Q.rear。若入队元素的速度快于出队元素的速度,则队尾指针很快就会赶上队首指针,如图 3.7(d1)所示,此时可以看出队满时也有Q.front==Q.rear。循环队列出入队示意图如图 3.7所示。

为了区分是队空还是队满的情况,有三种处理方式:

1)  牺牲一个单元来区分队空和队满,入队时少用一个队列单元,这是一种较为普遍的做法,约定以“队头指针在队尾指针的下一位置作为队满的标志”,如图 3.7(d2)所示。

  • 队满条件:(Q.rear+1)%MaxSize==Q.front。
  • 队空条件:Q.front==Q.rear。
  • 队列中元素的个数:(Q.rear-Q.front+MaxSize)%MaxSize。

2)  类型中增设 size 数据成员,表示元素个数

删除成功 size 减 1,插入成功 size 加 1。队空时 Q.size==0;队满时Q.size==Maxsize,两种情况都有Q.front==Q.rear。

3)  类型中增设 tag 数据成员,以区分是队满还是队空

删除成功置 tag=0,若导致Q.front==Q.rear,则为队空;插入成功置 tag=1,若导致 Q.front==Q.rear,则为队满。

3.2.3队列的链式存储结构

根据需求分析队列适合的存储结构(2019)】

队列的链式表示称为链队列,它实际上是一个同时有队头指针和队尾指针的单链表。头指针指向队头结点,尾指针指向队尾结点,即单链表的最后一个结点。

队列的链式存储类型可描述为:

typedef struct linkNode(      //链式队列结点
    ElemType data;
    struct linkNode *next;
}LinkNode;
typedef struct{               //链式队列
    LinkNode *front,*rear;    //队列的队头和队尾指针
}LinkQueue;

不带头结点时,当Q.front==NULL且Q.rear==NULL时,链式队列为空。

链式队列队空的判断(2019)】

入队时,建立一个新结点,将新结点插入到链表的尾部,并让Q.rear 指向这个新插入的结点(若原队列为空队,则令Q.front也指向该结点)。出队时,首先判断队是否为空,若不空,则取出队头元素,将其从链表中摘除,并让Q.front 指向下一个结点(若该结点为最后一个结点,则置Q.front 和Q.rear 都为 NULL)。

不难看出,不带头结点的链式队列在操作上往往比较麻烦,因此通常将链式队列设计成一个带头结点的单链表,这样插入和删除操作就统一了,如图3.9所示。

 

用单链表表示的链式队列特别适合于数据元素变动比较大的情形,而且不存在队列满且产生溢出的问题。另外,假如程序中要使用多个队列,与多个栈的情形一样,最好使用链式队列,这样就不会出现存储分配不合理和“溢出”的问题。

链式队列出队/入队操作的基本过程(2019)】 

(1)初始化

void InitQueue(LinkQueue &Q){    //初始化带头结点的链队列
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode)); //建立头结点
Q.front->next-NULL;              //初始为空
}

(2)判队空

bool IsEmpty(LinkQueue Q){
    if(Q.front==Q.rear)     //判空条件
        return true;
    else
        return false;
}

(3)入队

void EnQueue(LinkQueue &Q,ElemType &x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode)); //创建新结点
s->data=x;
s->next=NULL;
Q.rear->next=s;    //插入链尾
Q.rear=s;          //修改尾指针

(4)出队

bool DeQueue(linkQueue &Q,ElemType &x){
    if(Q.front==Q.rear)
        return false;            //空队
    LinkNode *p=Q.front->next;
    x=p->data;
    Q.front->next=p->next;
    if(Q.rear==p)
        Q.rear=Q.front;          //若原队列中只有一个结点,删除后变空
    free(p);
    return true;
}

3.2.4双端队列

双端队列出队/入队操作模拟(2010、2021)】

双端队列是指允许两端都可以进行插入和删除操作的线性表,如图3.10所示。双端队列两端的地位是平等的,为了方便理解,将左端也视为前端,右端也视为后端

在双端队列进队时,前端进的元素排列在队列中后端进的元素的前面,后端进的元素排列在队列中前端进的元素的后面。在双端队列出队时,无论是前端还是后端出队,先出的元素排列在后出的元素的前面

输出受限的双端队列:允许在一端进行插入和删除,但在另一端只允许插入的双端队列称为输出受限的双端队列

输入受限的双端队列:允许在一端进行插入和删除,但在另一端只允许删除的双端队列称为输入受限的双端队列。

若限定双端队列从某个端点插入的元素只能从该端点删除,则该双端队列就蜕变为两个栈底相邻接的栈。

 

  • 36
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心碎烤肠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值