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

数据结构——队列

时间:2024-09-02 10:26:24浏览次数:6  
标签:return 队列 data st int 数据结构 DATA

文章目录

队列

基本概念

队列是最常见的概念,日常生活经常需要排队,仔细观察队列会发现,队列是一种逻辑结构,是一种特殊的线性表。特殊在:

只能在固定的两端操作线性表

只要满足上述条件,那么这种特殊的线性表就会呈现一种“先进先出”的逻辑,这种逻辑就被称为队列。

由于约定了只能在线性表固定的两端进行操作,于是给队列这种特殊的线性表的插入删除,起个特殊的名称:

  • 队头:可以删除节点的一端

  • 队尾:可以插入节点的一端

  • 入队:将节点插入到队尾之后,函数名通常为enQueue()

  • 出队:将队头节点从队列中剔除,函数名通常为outQueue()

  • 取队头:取得队头元素,但不出队,函数名通常为front()

由于这种固定两端操作的简单约定,队列获得了“先进先出”的基本特性

顺序存储的队列:循环队列

与其他的逻辑结构类似,队列可以采用顺序存储形成循环队列,也可以采用链式存储形成链式队列。顺序存储的队列之所以被称为循环队列,是因为可以利用更新队头队尾的下标信息,来循环地利用整个数组,出队入队时也不必移动当中的数据。循环队列示意图如下所示:

请添加图片描述

从上述动图中可以观察到,需要牺牲至少数组中的一个存储位置,来区分循环队列中的满队和空队。满队和空队的约定如下:

  • 当front与rear相等时,队列为空
  • 当rear循环加一与front相等时,队列为满

与其他数据结构一样,管理循环队列除了需要一块连续的内存之外,还需要记录队列的总容量、当前队列的元素个数、当前队头、队尾元素位置,如果有多线程还需要配互斥锁和信号量等信息,为了便于管理,通常将这些信息统一于在一个管理结构体之中:

typedef int DATA;
typedef struct
{
    DATA *pData; // 队列入口
    int size; // 队列总容量
    int head; // 队列队头元素下标
    int tail; // 队列队尾元素下标
}SQueue;

循环队列的基本操作

squeue.h

#ifndef __SQUEUE_H
#define __SQUEUE_H
typedef int DATA;
typedef struct
{
    DATA *pData; // 队列入口
    int size; // 队列总容量
    int head; // 队列队头元素下标
    int tail; // 队列队尾元素下标
}SQueue;
// 初始化队列
int SQ_init(SQueue *q, int num);
// 判断队列是否已满
int SQ_isfull(SQueue *q);
// 判断队列是否为空
int SQ_isempty(SQueue *q);
// 入队
int SQ_push(SQueue *q,DATA data);
// 出队
int SQ_pop(SQueue *q,DATA *data);
// 回收队
int SQ_free(SQueue *q);
#endif
  • squeue.c

    #include <stdlib.h>
    #include "squeue.h"
    // 初始化队列
    int SQ_init(SQueue *q, int num)
    {
        q->pData = (DATA *)calloc(sizeof(DATA), num);
        if (q->pData == NULL)
            return -1;
        q->size = num;
        q->head = q->tail = 0;
        return 0;
    }
    // 判断队列是否已满
    int SQ_isfull(SQueue *q)
    {
        return (q->tail + 1) % q->size == q->head;
    }
    // 判断队列是否为空
    int SQ_isempty(SQueue *q)
    {
        return q->tail == q->head;
    }
    // 出队
    int SQ_push(SQueue *st, DATA data)
    {
        if (SQ_isfull(st))
            return -1;
        st->pData[st->tail] = data;
        st->tail = (st->tail + 1) % st->size;
        return 0;
    }
    // 入队
    int SQ_pop(SQueue *st, DATA *data)
    {
        if (SQ_isempty(st))
            return -1;
        *data = st->pData[st->head];
        st->head = (st->head + 1) % st->size;
        return 0;
    }
    // 回收队列
    int SQ_free(SQueue *st)
    {
        if (st->pData)
        {
            free(st->pData);
            st->pData = NULL;
        }
        st->head = st->tail = 0;
    }
    

    注意:

    循环队列中,需要牺牲一个存储位置来区分空队和满队

链式存储的队列:链式队列

链式队列的组织形式与链表无异,只不过插入删除被约束在固定的两端。为了便于操作,通常也会创建所谓管理结构体,用来存储队头指针、队尾指针、队列元素个数等信息:

请添加图片描述

从上图可以看到,链式队列主要控制队头和队尾,由于管理结构体中保存了当前队列元素个数size,因此可以不必设计链表的头节点,初始化空队列时只需要让队头队尾指针同时指向空即可。

以下是队列链表节点设计和管理结构体设计的示例代码:

typedef int DATA;
// 链式队列节点
typedef struct _node
{
    DATA data;
    struct _node *next;
}NODE/*,*PNODE*/;
// 链式队列管理结构体
typedef struct
{
    NODE *pHead; // 队头指针
    NODE *pTail; // 队尾指针
    int size ; // 队列当前元素个数
    int num ;
}LinkQueue;

链式队列的基本操作

linkQueue.h

#ifndef __LINKQUEUE_H
#define __LINKQUEUE_H
typedef int DATA;
// 链式队列节点
typedef struct _node
{
    DATA data;
    struct _node *next;
}NODE/*,*PNODE*/;
// 链式队列管理结构体
typedef struct
{
    NODE *pHead; // 队头指针
    NODE *pTail; // 队尾指针
    int size ; // 队列当前元素个数
    int num ;
}LinkQueue;
void LQ_init(LinkQueue *q,int sz);
int LQ_isfull(LinkQueue *q);
int LQ_isempty(LinkQueue *q);
int LQ_push(LinkQueue *q,DATA data);
int LQ_pop(LinkQueue *q,DATA *data);
int LQ_free(LinkQueue *q);
#endif

linkQueue.c

#include "LinkQueue.h"
#include <stdlib.h>
void LQ_init(LinkQueue *q, int sz)
{
    q->pHead = q->pTail = NULL;
    q->size = sz;
    q->num = 0;
}
int LQ_isfull(LinkQueue *q)
{
    return q->num == q->size;
}
int LQ_isempty(LinkQueue *q)
{
    return q->num == 0;
}
int LQ_push(LinkQueue *q, DATA data)
{
    if (LQ_isfull(q))
        return -1;
    NODE *pNew = (NODE *)malloc(sizeof(NODE));
    if (!pNew)
        return -1;
    pNew->data = data;
    pNew->next = NULL;
    if (!(q->pTail))
        q->pHead = q->pTail = pNew;
    else
    {
        q->pTail->next = pNew;
        q->pTail = pNew;
    }
    q->num++;
    return 0;
}
int LQ_pop(LinkQueue *q, DATA *data)
{
    if (LQ_isempty(q))
        return -1;
    NODE *p = q->pHead;
    *data = p->data;
    if (p == q->pTail)
        q->pHead = q->pTail = NULL;
    else
        q->pHead = p->next;
    free(p);
    q->num--;
    return 0;
}
int LQ_free(LinkQueue *queue)
{
    NODE *p = queue->pHead, *q = NULL;
    while (p)
    {
        q = p;
        p = p->next;
        free(q);
    }
    queue->pHead = queue->pTail = NULL;
    queue->num = 0;
    return 0;
}

标签:return,队列,data,st,int,数据结构,DATA
From: https://blog.csdn.net/qixi_ao/article/details/141688451

相关文章

  • PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
    大家好,我是码农先森。我们在某宝或某多多上抢购商品时,如果只是下了订单但没有进行实际的支付,那在订单页面会有一个支付倒计时,要是过了这个时间点那么订单便会自动取消。在这样的业务场景中,一般情况下就会使用到延时队列。通常在客户下单之后,就会将订单数据推送到延时队列中并且......
  • RabbitMQ 队列使用基础教程
    实践环境JDK1.8.0_121amqp-client5.16.0附:查看不同版本的amqp-client客户端支持的JavaJDK版本https://www.rabbitmq.com/client-libraries/java-versionsmavnsettings.xml<?xmlversion="1.0"encoding="UTF-8"?><settingsxsi:schemaLocation="h......
  • 介绍数据结构和数据类型这两个概念及其区别。
    数据结构数据结构(datastructure)是相互之间存在一种或多种特定关系的数据元素的集合。一个数据结构一般包含数据逻辑结构、存储结构和数据运算三个方面。简单来说就是数据的逻辑或物理存储方式,以便可以高效地访问和修改数据。数据类型数据类型(datatype)是一个值的集合和......
  • Java消息队列:RabbitMQ与Kafka的集成与应用
    Java消息队列:RabbitMQ与Kafka的集成与应用大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代的分布式系统中,消息队列是实现系统间通信、解耦和提高可扩展性的重要组件。RabbitMQ和Kafka是两个广泛使用的消息队列系统,它们各有特点和优势。本文将介......
  • 58集团23校招测试工程师卷——考查队列
    编程题-操作系统先入先出算法实现1234567891011在操作系统的页面置换算法中,当需要淘汰一个页面的时候,可以针对先进入主存的页面先淘汰;现在针对这个算法请实现一个简易版的程序,实现在页面数达到内存上限时,通过先入先出的算法淘汰置换并输出最后保留在内存中的......
  • 数据结构:(LeetCode572)另一棵子树
    给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。示例1:......
  • 数据结构—堆
    一、树的概念及及结构在我们学习堆时,首先要了解树,因为堆其实是一种特殊树。在数据结构中,树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。像下面图一样:每一个树都有一个特......
  • 【链式队列的实现】
    1.链式队列与循环顺序队的比较1.1链式队列优点动态扩展:不需要预先分配固定的存储空间,内存使用灵活,不会因为队列满而导致溢出。插入和删除操作简单:在链式队列中,插入和删除操作只需调整指针,无需移动数据,时间复杂度为O(1)。无容量限制:只要系统有足够的内存,链式......
  • 数据结构 栈与队列 --循环队列
    栈和队列--循环队列文章目录栈和队列--循环队列前言一、队列是什么?1.2时间复杂度比较1.3难题及解决二、队列的实现2.1循环队列结构体实现2.2循环队列基本操作总结前言前情提要:之前的文章讲了队列和栈的基本概念,今天来讲队列的具体实现一、队列是什么?队......
  • 栈和队列(1)——顺序栈,链栈
    数据结构:栈和队列(1)–顺序栈,链栈提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录数据结构:栈和队列(1)--顺序栈,链栈前言一、栈和队列1.1栈和队列的定义1.2队列的定义二、栈实现操作2.1顺序栈的结构体定义2.2顺序栈的基本操作:2.3链栈的结构体定......