24考研数据结构-队列2

目录

  • 数据结构之队列:链式存储结构与循环队列
    • 链式存储结构
      • 链式队列的结构
      • 链式队列的操作
    • 循环队列
      • 循环队列的结构
      • 循环队列的操作
    • 链式队列与循环队列的比较
    • 结论
    • 3.2.3 队列的链式存储结构
      • 3.2.3.1定义
      • 3.2.3.2链式队列的基本操作——带头结点
      • 3.2.3.3 不带头结点的相关操作
    • 3.2.4双端队列
      • 0. 限制输入输出问题(需要再验证)
      • 1.定义
    • 3.2.5循环队列

数据结构之队列:链式存储结构与循环队列

在计算机科学中,队列是一种常见的数据结构,它遵循先进先出(FIFO)的原则,即最先入队的元素将最先出队。队列广泛应用于计算机系统中,例如任务调度、缓冲区管理等。在队列的实现中,链式存储结构和循环队列是两种常见的方法。本文将对这两种队列的实现方法进行介绍和比较。

链式存储结构

链式存储结构是通过链表来实现队列的一种方法。队列中的每个元素被封装成一个节点,节点之间通过指针链接在一起。链式队列允许动态地添加和删除元素,不需要事先定义队列的大小,因此具有较好的灵活性。

链式队列的结构

一个链式队列节点通常包含两个部分:

  • 数据域:用于存储节点所包含的数据。
  • 指针域(next):指向队列中下一个节点的指针。
struct QueueNode {
    int data;
    QueueNode* next;
};

链式队列的操作

链式队列支持多种操作,包括元素的入队和出队等。由于队列的元素在链表中动态存储,因此链式队列的大小可以根据实际需求进行调整,不会浪费内存空间。

循环队列

循环队列是一种使用数组实现的队列。与链式队列相比,循环队列具有固定大小,一旦队列的大小被定义,就无法动态扩展。循环队列通过“头指针”和“尾指针”来实现循环存储,当队列满时,新元素将覆盖最先入队的元素,实现循环使用队列空间。

循环队列的结构

循环队列通常包含以下几个部分:

  • 数据数组:用于存储队列中的元素。
  • 头指针(front):指向队列头部的位置。
  • 尾指针(rear):指向队列尾部的下一个位置。
#define MAX_SIZE 100

class CircularQueue {
private:
    int data[MAX_SIZE];
    int front;
    int rear;

public:
    CircularQueue();
    bool isEmpty();
    bool isFull();
    void enqueue(int value);
    int dequeue();
};

循环队列的操作

循环队列支持多种操作,包括元素的入队和出队等。由于队列是循环使用数组空间,因此入队和出队操作需要更新头指针和尾指针,并考虑数组下标的循环。

链式队列与循环队列的比较

链式队列和循环队列是两种不同的队列实现方式,它们各自具有优势和适用场景。

链式队列的优势:

  • 动态大小:链式队列可以根据实际需求动态调整大小,不会浪费内存空间。
  • 灵活性:链式队列允许动态添加和删除元素,操作更加灵活。

循环队列的优势:

  • 固定大小:循环队列使用数组实现,具有固定大小,不会频繁申请和释放内存,效率较高。
  • 循环利用:循环队列通过循环使用队列空间,可以有效地利用数组空间,减少内存碎片。

结论

链式存储结构和循环队列是两种常见的队列实现方法。在选择使用哪种队列实现时,需要根据具体的应用场景和操作需求来进行判断。无论是链式队列还是循环队列,队列数据结构在计算机科学中扮演着重要的角色,为我们提供了高效管理数据的方法。

3.2.3 队列的链式存储结构

3.2.3.1定义

1.定义:队列的链式表示称为链队列,它实际上是一个同时带有队头指针和队尾指针的单链表。
链队列:用链表表示的队列,是限制仅在表头删除和表尾插入的单链表。
队列的链式存储类型可描述为:

typedef struct LinkNode{      //链式队列结点
    ElemType data;
    struct LinkNode *next;
}

typedef struct{               //链式队列
    LinkNode *front, *rear;   //队列的队头和队尾指针
}LinkQueue;


3.2.3.2链式队列的基本操作——带头结点

24考研数据结构-队列2_第1张图片

  • 初始化 & 判空
void InitQueue(LinkQueue &Q){
    //初始化时,front、rear都指向头结点
    Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
    Q.front -> next = NULL;
}

//判断队列是否为空
bool IsEmpty(LinkQueue Q){
    if(Q.front == Q.rear)     //也可用 Q.front -> next == NULL
        return true;
    else
        return false;
}
  • 入队操作
//新元素入队 (表尾进行)
void EnQueue(LinkQueue &Q, ElemType x){
    LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); //申请一个新结点
    s->data = x;
    s->next = NULL;     //s作为最后一个结点,指针域指向NULL
    Q.rear->next = s;   //新结点插入到当前的rear之后
    Q.rear = s;         //表尾指针指向新的表尾
}


  • 出队操作
//队头元素出队
bool DeQueue(LinkQueue &Q, ElemType &x){
    if(Q.front == Q.rear)
        return false;                    //空队
    
    LinkNode *p = Q.front->next;         //p指针指向即将删除的结点 (头结点所指向的结点)
    x = p->data;
    Q.front->next = p->next;             //修改头结点的next指针
    if(Q.rear == p)                      //此次是最后一个结点出队
        Q.rear = Q.front;                //修改rear指针
    free(p);                             //释放结点空间

    return true;
}

在这里插入图片描述

  • 队列满的条件
    顺序存储:预分配存储空间
    链式存储:一般不会队满,除非内存不足

  • 计算链队长度 (遍历链队)
    设置一个int length 记录链式队列长度


3.2.3.3 不带头结点的相关操作

24考研数据结构-队列2_第2张图片
24考研数据结构-队列2_第3张图片
24考研数据结构-队列2_第4张图片

3.2.4双端队列

0. 限制输入输出问题(需要再验证)

对于双端队列的限制输出以及输出问题,做以下考虑

  • 限制输入的,就意味着单边输入,注意输入顺序,怎么输入就怎么按照什么顺序写下去,再去左右判断是否可以输出
  • 限制输出的,就意味着单边输出,注意输出顺序,按照输入顺序的第一个,选项中左右寻找临近的输入顺序,找得到则合法

1.定义

双端队列是指允许两端都可以进行入队和出队操作的队列

  • 双端队列允许从两端插入、两端删除的线性表;
  • 如果只使用其中一端的插入、删除操作,则等同于栈;
  • 输入受限的双端队列:允许一端插入,两端删除的线性表;
  • 输出受限的双端队列:允许两端插入,一端删除的线性表;

栈合法的序列,双端序列也合法(只用一边就是一个栈),所以只要考虑不合法的那些

3.2.5循环队列

24考研数据结构-队列2_第5张图片

你可能感兴趣的:(408,#,数据结构,考研,数据结构,笔记,学习,算法)