2024年王道考研数据结构——队列

本文详细介绍了队列的基本概念,包括顺序存储的局限、循环队列的实现、链式存储的队列以及双端队列的特点。还通过选择题和综合应用题的形式探讨了队列的入队和出队操作,以及如何用栈模拟队列和逆序队列的操作。

队列

注:本节开始,我会在开头对本节内容的基础内容进行一个归纳,然后才是习题。

队列基础知识:

队列也是一种操作受限的线性表,其特征是先进先出,只能在队首出,队尾进,类似于排队。

不同存储方式的队列

1),顺序存储

#define Maxsize 50
typedef struct queue{
    elemtype data[Maxsize];
    int front , rear;
}SQqueue;

普通的顺序存储存在的问题是当前面入队的数据弹出后,front后移,而front之前的空间就浪费了,有空的空间,但是确无法再入队。

此时针对这个问题,对顺序存储进行一定的调整,使之变为环形,于是就有了循环队列

循环队列:

对front 和rear 进行对队长取余就可以实现,这样当队列空时,front = rear ,队满时可以用不同的方法确定。

大部分情况下都是约定rear + 1 == front 的情况为满队。

2),队列的链式存储结构

typedef struct Linknode{
    int data;
    struct Linknode *Next;
}Linknode;

typedef struct{
    Linknode *front , *rear;
}*Linkqueue;

front 指针指向头结点,rear指向尾结点,入队就用尾插法,出队就是删除第一个结点,每次入队都要更新rear。

3),双端队列

队列可以从两边进行插入和删除

输入受限的双端队列:输入只能从一端输入,输出可以从两边输出

输出受限的双端队列:输出只能从一端输出,输入可以从两边输入

一,选择题
1,栈和队列的主要区别是:

插入和删除的操作的限定不一样

2,循环队列存储在数组A[0…n]中,入队时的操作是

rear = (rear + 1) % (n+1);

注:取余不是n是因为,当n为n-1时插入元素则会直接跳转到0,而不会到n,所以是取余n+1而不是n;

3,用链式存储方式的队列进行删除操作时需要:头尾指针都有可能要修改

∵链式队列里,插入是使用的尾插法,所以要删除元素时,是删除链表的第一个元素,但是当队列里只有一个元素的时候,删除元素就需要修改队首指针也需要修改队尾指针。

4,若以1,2,3,4作为双端队列的输入序列,则既不能用输出受限的双端队列输出,也不能用输入受限的双端队列输出的输出序列是:4,2,3,1

对于输出受限的双端队列,入队顺序是1,2,3,4所以3没办法插在1,2中间

对于输入受限的双端队列,2没法比3和1先输出,因为2肯定在1,3中间

5,已知循环队列存储在一维数组A[0…n-1]中,切队列非空时要求front指向队头元素而rear指向队尾元素,初始队列为空,要求现在输入一个数据,使得存放在A[0],则初始时front和rear分别为多少。

因为初始为空插入后front依然是队首,所以front不用改变依然是0,所以front原来就是0,因为在插入一个元素后,rear要进行+1然后mod n,如果开始为0,则第一个元素进来后会变成1,而初始为n-1时,就是A[0]所以front和rear分别为0,n-1;

二,综合应用题
1,写出一个用tag为0|1表示队列空与否的循环队列的入队和出队操作。

队列的结构和初始化

struct SQqueue{
    int data[Maxsize];
    int front , rear ,tag;
}SQqueue;

void init_queue(SQqueue q)
{
    q.front = q.rear = 0;
    tag = 0;//tag == 0 表示此时队空
}

入队操作

bool push(SQqueue q , int x)
{
    if(q.front == q.rear && q.tag == 1)return false;//判断是否满队
    q.data[q.rear] = x;
    q.rear = (q.rear++)%Maxsize;
    if(q.rear == q.front)tag = 1;
    return true;
}

出队操作

bool front(SQqueue q , int &x)
{
    if(q.front == q.rear && q.tag == 0)return false;//判断是否队空
    x = q.data[q.front];
    q.front = (q.front++)%Maxsize;
    if(q.front == q.rear) tag =0;
    return true;
}
2,Q是一个队列,S是一个栈,实现将队列中的元素逆置。

思路:弹出然后入栈,全部入栈了再重新入队,太简单了难得写没意义

3,用两个栈来模拟一个队列

push(s,x) //元素x入栈s

pop(s,x) //出栈将栈顶元素给x

stackempty(s) //判断栈是否为空

stackoverflow(s) //判断是否栈满

用以上的操作模拟队列一下操作

enqueue //元素x入队

dequeue //元素出队

queueempty //判断是否为空队列

思路:将入队的序列用逆序存入栈内就可以使出栈顺序变成出队的顺序。所以我们用s2来逆序入队元素,用s1当队列的存储的位置。

void enqueue(int x)
{
if(stackoverflow(s1))
{
    //如果满了就不能入队
return false;
}
    int m;
    while(!stackempty(s1))//先将原来的压入s2,然后再将全部压回s1.
    {
    pop(s1,m);
    push(s2,m);
    }
    push(s2,x);
    while(!stackempty(s2))
    {
        pop(s2,m);
        push(s1,m);
    }

}

void dequeue(int &x)
{
    pop(s1,x); //出队直接s1出栈就行。
}

bool queueempty()
{
    if(stackempty(s1))//s1不为空队列就不为空。
    {
    return true;
    }
return false;
}

第四题就不写了,不想写了。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值