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

数据结构-队列

时间:2023-11-10 14:00:58浏览次数:47  
标签: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最近的请求次数

2、广度优先搜索

LeetCode542.01矩阵

LeetCode994腐烂的橘子

七、队列的进阶

1、辅助队列

LeetCode225用队列实现栈

LeetCode 1696. 跳跃游戏 VI

LeetCode 1438. 绝对差不超过限制的最长连续子数组

LeetCode 239. 滑动窗口最大值

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

相关文章

  • 数组&队列&关联数组的总结
    定宽数组:可以直接赋值,也可以先声明再赋值其中还有多维数组intarray2[0:7][0:3];intarray3[8][4];//先个后位intascend[4]='{0,1,2,3};intdescend[5];descend='{4,3,2,1,0};descend[0:2]='{5,6,7};ascend='{4{8}};descend='{9,8,default:-1};数组的声明全在左......
  • 数据结构入门 — 顺序表详解
    前言数据结构入门—顺序表详解关注博主,后期持续更新系列文章文章末尾有源码*****感谢观看,希望对你有所帮助*****文章目录前言一、顺序表1.顺序表是什么2.优缺点二、概念及结构1.静态顺序表2.动态顺序表三、顺序表接口实现(代码演示)1.动态存储结构2.顺序表打印3.顺序表初......
  • 数据结构入门 — 链表详解_双向链表
    前言数据结构入门—双向链表详解*关注博主,后期持续更新系列文章文章末尾有源码*****感谢观看,希望对你有所帮助*****系列文章第一篇:数据结构入门—链表详解_单链表第二篇:数据结构入门—链表详解_双向链表第三篇:数据结构入门—链表详解_循环链表文章目录前言系列文章什......
  • Kafka队列
    ......
  • 自己写数据结构
    #include<iostream>#include<array>template<typenameT,size_tS>classArray{private: Tm_data[S];public: constexprintSize()const{ returnS; } T&operator[](intindex){returnm_data[index];} constT&operator[](in......
  • Redis队列和阻塞队列
    redis队列的优点是轻量级,业务足够简单时不需要使用rabbitMq这样专业的消息中间件;缺点是弹出队列中的元素时,即使该消息处理失败也无法再次进行消费Redis队列List简单演示如下普通的redis队列,为了实现业务,通常会使用while进行循环,这样的话没有消息时依旧会频繁的执行循环,造成cpu的......
  • 高级数据结构学习笔记
    0.普适技巧动态开点:节省空间。标记永久化:分块的块标记本质就是这个。可以节省空间。1.区间最值&历史区间最值link2.二维线段树二维区间静态:二维ST表二维前缀动态:二维树状数组二维区间动态:二维线段树例题:LuckandLove、P3157[CQOI2011]动态逆序......
  • 数据结构的两个层次
    逻辑结构:描述数据元素之间的逻辑关系与数据的存储无关,独立于计算机是从具体问题抽象出来的数学模型 2.物理结构(存储结构)数据元素及其关系在计算机存储器中的结构(存储方式)是数据结构在计算机的表示 关系:存储结构是逻辑关系的映象与元素本身的映象逻辑......
  • BlockingQueue队列详解
    /**本例介绍一个特殊的队列:BlockingQueue,如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒.同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有空间才会被......
  • 04-栈和队列
    4.栈和队列栈:push,pop,peek(返回当前值),empty队列:add,remove,peek(返回当前值),isEmpty4.1双向链表实现栈和队列4.2数组实现栈和队列加一个指针指向某个位置。队列:环形数组4.3最小栈1.题目https://leetcode.cn/problems/min-stack/设计一个支持push,pop,top操作,并能在常数......