首页 > 其他分享 >数据结构-队列

数据结构-队列

时间:2023-11-06 22:39:17浏览次数:38  
标签:head struct 队列 Queue tail que 数据结构

一、概念

1、队列的定义

队列是仅限在一端进行插入另一端进行删除的线性表

队列又被称为先进先出(First In First Out) 的线性表,简称 FIFO 。

2、队首

允许进行元素删除的一端称为队首

数据结构-队列_队列

3、队尾

允许进行元素插入的一端称为 队尾

数据结构-队列_数组_02

二、接口

1、可写接口

(1)数据入队

队列的插入操作,叫做 入队。它是将 数据元素队尾 进行插入的过程

数据结构-队列_算法_03

(2)数据出队

队列的删除操作,叫做 出队。它是将 队首 元素进行删除的过程

数据结构-队列_链表_04

(3)清空队列

队列的清空操作,就是一直 出队,直到队列为空的过程,当 队首队尾 重合时,就代表队尾为空了

2、只读接口

(1)获取队首数据

对于一个队列来说只能获取 队首 数据,一般不支持获取 其它数据。

(2)获取队列元素个数

 队列元素个数一般用一个额外变量存储,入队 时加一,出队 时减一

(3)队列的判空

当队列元素个数为零时,就是一个 空队空队 不允许 出队 操作

三、队列的顺序表实现

1、结构体

struct Queue {             // 队列结构体

    DataType data[maxn];   // 队列存储方式,数组

    int head, tail;        // 队首,队尾指针,head == tail代表空队

};

2、入队

void QueueEnqueue(struct Queue *que, DataType dt) {  

    que->data[ que->tail ] = dt;                     // 将传参的元素入队

    que->tail = que->tail + 1;                       // 队尾指针加一

}

可以写成下面这样

void QueueEnqueue(struct Queue *que, DataType dt) {

    que->data[ que->tail++ ] = dt;

}

3、出队

void QueueDequeue(struct Queue* que) {

    ++que->head;//队首指针加一

}

4、清空队列

清空队列的操作只需要将 队首指针队尾指针 都归零即可

void QueueClear(struct Queue* que) {

    que->head = que->tail = 0;

}

5、只读接口

DataType QueueGetFront(struct Queue* que) {

    return que->data[ que->head ];      // 得到队首元素

}

int QueueGetSize(struct Queue* que) {

    return que->tail - que->head;       // 队列的元素个数

}

int QueueIsEmpty(struct Queue* que) {

    return !QueueGetSize(que);          // 判空

}

6、队列的顺序表实现的源码

#define DataType int

#define maxn 100005


struct Queue {

    DataType data[maxn];

    int head, tail;

};


void QueueClear(struct Queue* que) {

    que->head = que->tail = 0;

}

void QueueEnqueue(struct Queue *que, DataType dt) {

    que->data[ que->tail++ ] = dt;

}

void QueueDequeue(struct Queue* que) {

    ++que->head;

}


DataType QueueGetFront(struct Queue* que) {

    return que->data[ que->head ];

}

int QueueGetSize(struct Queue* que) {

    return que->tail - que->head;

}

int QueueIsEmpty(struct Queue* que) {

    return !QueueGetSize(que);

}

四、队列的链表实现

1、结构体

typedef int DataType;               

struct QueueNode;                  

struct QueueNode {                  // 结点

    DataType data;

    struct QueueNode *next;

};


struct Queue {

    struct QueueNode *head, *tail;  // 队首、队尾指针

    int size;                       // 队列元素个数

};

2、入队

链表入队类似尾插法

void QueueEnqueue(struct Queue *que, DataType dt) {

    struct QueueNode *insertNode = (struct QueueNode *) malloc( sizeof(struct QueueNode) );            
    insertNode->data = dt;                  // 给入队的元素赋值

    insertNode->next = NULL;

    if(que->tail) {                         // 不为空

        que->tail->next = insertNode;

        que->tail = insertNode;

    }else {

        que->head = que->tail = insertNode; // 为空直接首队尾指针指向新入队的元素

    }

    ++que->size;                            // 元素个数加一

}

3、出队

出队 操作,由于链表头结点就是 队首,其实就是删除这个链表的头结点的过程

void QueueDequeue(struct Queue* que) {

    struct QueueNode *temp = que->head;  // 将队首保存到temp

    que->head = temp->next;              // 队首指向temp的下一个结点,也就是队首的下一个结点

    free(temp);                          // 释放temp

    --que->size;                         // 长度减一

    if(que->size == 0) {                 // 如果长度为0,队尾置空

        que->tail = NULL;

    }  
}

4、清空队列

对于链表而言,清空队列 的操作需要删除每个链表结点

void QueueClear(struct Queue* que) {

    while(!QueueIsEmpty(que)) {     // 队列不为空

        QueueDequeue(que);          // 出队

    }

}

5、只读接口

DataType QueueGetFront(struct Queue* que) {

    return que->head->data;              // 得到队首元素

}

int QueueGetSize(struct Queue* que) {

    return que->size;                    // 队列元素个数

}

int QueueIsEmpty(struct Queue* que) {

    return !QueueGetSize(que);           // 是否为空

}

6、队列的链表实现源码

typedef int DataType;


struct QueueNode;

struct QueueNode {

    DataType data;

    struct QueueNode *next;

};


struct Queue {

    struct QueueNode *head, *tail;

    int size;

};


void QueueEnqueue(struct Queue *que, DataType dt) {

    struct QueueNode *insertNode = (struct QueueNode *) malloc( sizeof(struct QueueNode) );

    insertNode->data = dt;

    insertNode->next = NULL;

    if(que->tail) {

        que->tail->next = insertNode;

        que->tail = insertNode;

    }else {

        que->head = que->tail = insertNode;

    }

    ++que->size;

}


void QueueDequeue(struct Queue* que) {

    struct QueueNode *temp = que->head;

    que->head = temp->next;

    free(temp);

    --que->size;

    if(que->size == 0) {

        que->tail = NULL;

    }  
}


DataType QueueGetFront(struct Queue* que) {

    return que->head->data;

}

int QueueGetSize(struct Queue* que) {

    return que->size;

}

int QueueIsEmpty(struct Queue* que) {

    return !QueueGetSize(que);

}

void QueueClear(struct Queue* que) {

    que->head = que->tail = NULL;

    que->size = 0;

}

五、优缺点

1、顺序表

入队出队 的常数时间复杂度低,且 清空队列 操作相比 链表实现 能做到O(1),

不足之处是:需要预先申请好空间,而且当空间不够时,需要进行扩容

2、链表

入队出队 的常数时间复杂度略高,主要是每插入一个队列元素都需要申请空间,每删除一个队列元素都需要释放空间,且 清空队列 操作是 O(n),直接将 队首指针队尾指针 置空会导致内存泄漏

好处就是:不需要预先分配空间,且在内存允许范围内,可以一直 入队

六、队列的入门

1、滑动窗口

LeetCode933最近的请求次数:https://leetcode.cn/problems/number-of-recent-calls/

2、广度优先搜索

LeetCode542.01矩阵:https://leetcode.cn/problems/01-matrix/

LeetCode994腐烂的橘子:https://leetcode.cn/problems/rotting-oranges/

七、队列的进阶

1、辅助队列

LeetCode225用队列实现栈:https://leetcode.cn/problems/implement-stack-using-queues/

2、单调队列

LeetCode 1696. 跳跃游戏 VIhttps://leetcode.cn/problems/jump-game-vi/

LeetCode 1438. 绝对差不超过限制的最长连续子数组:https://leetcode.cn/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/

LeetCode 239. 滑动窗口最大值:https://leetcode.cn/problems/sliding-window-maximum/



标签:head,struct,队列,Queue,tail,que,数据结构
From: https://blog.51cto.com/u_15858858/8217715

相关文章

  • 单调队列学习笔记
    Menu单调队列(MonotonicQueue)简介代码模板例题单调栈(MonotonicStack)简介代码模板例题......
  • 数据结构
    数据的逻辑结构:线性逻辑结构:一对一除第一个和最后一个元素外,数据的每一个元素都有且只有一个直接前驱和一个直接后继树型逻辑结构:一对多有且只有一个称为根的数据元素;根没有前驱,其余的每个元素有且只有一个前驱,末端元素没有......
  • 【Java集合】数据结构与集合的神秘联系,一文读懂!
    上篇文章中我们对单列集合中常用的方法和遍历查询。通过本文章为我们解惑,好好的字符串用起来不就行了,为什么要用集合这些工具类?本篇文章将简要介绍数据结构,让读者了解它们在计算机中以何种结构方式存在。那么,什么是数据结构呢?下面我们来详细解释。数据结构1.1数据结构有什么用?......
  • 队列(阻塞队列、非阻塞队列)的详解
    队列的详解什么是队列?用来存储一条条消息(线程)的容器是一个对列。队列是一种特殊的线性表,遵循先入先出、后入后出的基本原则什么是阻塞队列,什么是非阻塞队列?阻塞队列:添加元素时,超过总数则会进行等待(阻塞)。删除元素时,队列为空则会进行等待(阻塞)。非阻塞队列:不管什么情况下都......
  • 数据结构与算法-数组
    什么是数组在每一种编程语言中,基本都会有数组这种数据类型。不过,它不仅仅是一种编程语言中的数据类型,还是一种最基础的数据结构是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据数组的特点低效的插入和删除数组为了保持内存数据的连续性,会导致插入......
  • 数据结构之排序
    一.什么是稳定排序?排序后相等元素的相对位置不发生变化二.稳定排序有哪些?2.1.不稳定排序:快速排序、希尔排序、堆排序2.2.稳定排序:冒泡排序、插入排序、归并排序、基数排序三.各大排序算法3.1.稳定算法3.1.1.冒泡排序思想:通过两两比较不断将最大的数浮出水面。一次浮出一......
  • 数据结构的基本概念和术语
    数据(Data)数据:能输入计算机且能被计算机处理的各种符号的集合,信息的载体能被计算机识别,存储和加工包括:数值型的数据:整数,实数等  非数值型的数据:文字,图像,声音等;2.数据元素和数据项数据元素:是数据的基本单位,在计算机程序......
  • 【MySQL】MVCC机制、ReadView数据结构、匹配规则详解
    (目录)MySQLMVCC机制1.隔离级别在MySQLInnoDB存储引擎下,RC、RR基于MVCC(多版本并发控制)进行并发事务控制MVCC是**基于”数据版本”**对并发事务进行访问2.场景分析UNDO_LOG不是会被删除吗?中间数据万一被删了版本链不就断了?UNDO_LOG版本链不是立即删除,MySQL确保版......
  • 数据结构的初认识
    一般,我们将数据结构分为逻辑结构和物理结构。逻辑结构:是指数据对象中数据元素的相互关系。逻辑结构包括:集合结构,线性结构,树型结构,图形结构。       物理结构:是指数据的逻辑结构在计算机中的存储形式。根据物理结构的定义,我们实际上研究的的就是如......
  • 数据结构与算法—绪论
    前言数据结构与算法是程序员内功体现的重要标准之一,且数据结构也应用在各个方面,业界更有程序=数据结构+算法这个等式存在。各个中间件开发者,架构师他们都在努力的优化中间件、项目结构以及算法提高运行效率和降低内存占用,在这里数据结构起到相当重要的作用。此外数据结构也蕴含一......