数据结构和算法(1) ---- Queue 的原理和实现

news2025/1/18 17:07:15
Queue 的定义和结构

队列(Queue) 是只允许在一端进行插入,在另一端进行删除的线性表
队列是一种先进先出(First In First Out)的线性表,简称 FIFO(First IN First OUT), 允许插入的一端称为队尾, 允许删除的一端称为队列头

队列的基本结构如下图所示:
queue struct

Queue 的抽象数据类型

队列也有线性表的各种操作,不同的是插入元素只能在队列尾,删除元素只能在对列头进行:
队列的抽象结构如下所示:

ADT Queue(队列)
Data:
    同线性表, 元素具有相同的类型,相邻的元素具有前驱和后继关系
Operation:
    InitQueue(Q*)
    DestroyQueue(Q*)
    isEmpty(Q*)
    isFull(Q*)
    dequeue(Q*, *e)
    enqueue(Q*, e)
    queueSize(Q)
endADT

队列有多种实现方式,比如 静态数组,动态数组,单链表,双链表等

静态数组实现Queue

静态数组实现队列的基本原理:

  • 建立一个 MAX_SIZE 的数组, 用于存放 Queue 中的元素
  • 建立int类型 queue->rear 代表队列尾, 每次 enqueue 一个元素时,queu->rear 指向最新的元素位置
    staticArrayEnqueue
  • 建立 queue->front 代表队列头, 每次 dequeue 一个元素,从 queue->front 位置处取出数据,并且最后其指向下一个元素位置
    StaticArrayDequeue
  • queue->rearqueue->front 相等时,queue->frontqueue->rear都重新设置为 0,此时队列为空,表示重新开始存储数据
    StaticArrayEqual
    参考代码如下:
#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE];
    int front;
    // queue 尾端的索引
    int rear;
}Queue;

void Queueinit(Queue* queue) {
    queue->front = -1;
    queue->rear = -1;
}

int isEmpty(Queue* queue) {
    return (queue->front == -1 && queue->rear == -1);
};

int isFull(Queue* queue) {
    // queue->rear == MAX_SIZE - 1  queue->front = 0
    //return (queue->rear + 1)%MAX_SIZE == queue->front;
    if((queue->rear + 1 - queue->front) == MAX_SIZE) {
        return 1;
    }

    return 0;
};

void enqueue(Queue* queue,int item) {
    if(isFull(queue)) {
        fprintf(stderr,"queue is full. \n");
        return;
    }

    //printf("queue front is %d rear is %d \n",queue->front,queue->rear);
    if(isEmpty(queue)) {
        queue->rear = 0;
        queue->front = 0;
    } else {
        queue->rear = (queue->rear+1)%MAX_SIZE;
    }

    queue->data[queue->rear] = item;
}

int dequeue(Queue* queue) {
    if(isEmpty(queue)) {
        fprintf(stderr,"queue is empty. \n");
        return -1;
    }

    int item = queue->data[queue->front];

    // with no element
    if(queue->front == queue->rear) {
        printf("queue has no element backup to empty\n");
        queue->front = -1;
        queue->rear = -1;
    } else {
        queue->front = (queue->front +1)%MAX_SIZE;
    }

    return item;
}

int peek(Queue* queue) {
    if(isEmpty(queue)) {
        fprintf(stderr,"queue is empty. \n");
        return -1;
    }
    return queue->data[queue->front];
}


int testbasicQueueStaticArray(int agrc, char *argv[]) {
    {
        Queue testqueue = {
            .front = -1,
            .rear = -1,
        };
        Queueinit(&testqueue);

        for(int i = 0; i < 2000; i++) {
            enqueue(&testqueue,200+i);
            dequeue(&testqueue);
        }

        enqueue(&testqueue,1001);
        enqueue(&testqueue,1002);
        enqueue(&testqueue,1003);
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("peek queue element: %d queue size:%d\n", peek(&testqueue),QueueSize(&testqueue));
    }

}
单链表实现Queue

单链表实现Queue的基本原理:

  • 建立一个单链表,包含指向队列头的指针queue->front 和指向队列尾的指针queue->rear

  • enqueue时,首先为新元素分配空间,然后插入到单链表的尾部,用queue->rear指向它
    LinkedListEnqueue

  • dequeue时,首先返回queue->front指向的节点内容,然后free掉queue->front节点,queue->front指向顺序的后一个节点
    LinkedListDequeue
    参考代码如下:

struct node {
    int data;
    struct node *next;
};

typedef struct {
    struct node *front;
    struct node *rear;
}Queue;

static int empty(Queue* queue){
    return (queue->front == NULL);
}

static void initQueue(Queue* queue) {
    queue->front = queue->rear = NULL;
}

static void push(Queue* queue, int value) {
    struct node *pnode;
    pnode = (struct node*)malloc(sizeof(struct node));
    if(pnode == NULL) {
        printf("malloc node failed!.\n");
        exit(1);
    }
    pnode->data = value;
    pnode->next = NULL;

    if(empty(queue)) {
        queue->front = pnode;
        queue->rear = pnode;
    } else {
        queue->rear->next= pnode;
        queue->rear = pnode;
    }
}

static int pop(Queue* queue) {
    if (empty(queue))
    {
        printf("Queue Underflow. Unable to remove.\n");
        exit(1);
    }
    int item;
    struct node *p = queue->front;
    item = queue->front->data;
    queue->front = queue->front->next;
    if (queue->front == NULL) /* Queue contained only one node */
        queue->rear = NULL;

    free(p);
    return item;
}

static int peek(Queue* queue) {
    if (empty(queue))
    {
        printf("Queue Underflow. Unable to remove.\n");
        exit(1);
    }
    return queue->front->data;
}

static int queueSize(Queue* queue){
    struct node *p = queue->front;
    int count = 0;
    if(empty(queue)){
        return 0;
    }

    do {
        p = p->next;
        count++;
    }while(p != NULL);

    return count;
}



int testbasicQueueImplsingleLinkedList(int agrc, char *argv[]) {
    {
        Queue testqueue;
        int qsize = 0;
        initQueue(&testqueue);
        push(&testqueue, 10);
        printf("queue size: %d. \n", queueSize(&testqueue));

        push(&testqueue, 101);
        push(&testqueue, 102);
        push(&testqueue, 103);
        push(&testqueue, 104);
        printf("queue size: %d. \n", queueSize(&testqueue));

        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        qsize = queueSize(&testqueue);
        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        qsize = queueSize(&testqueue);
        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        qsize = queueSize(&testqueue);
        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        printf("queue size: %d. \n", queueSize(&testqueue));
        printf("peek value: %d  \n", peek(&testqueue));
        printf("queue size: %d. \n", queueSize(&testqueue));

    }
    return 1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1853195.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

百老开通知识星球啦,数据要素、数据治理等资料迅速扩散!

1.写在前面&#xff1a; 做数据相关工作有一些年头了&#xff0c;手里也积攒了几千份案例、解决方案、考试认证资料、数据要素研报等材料&#xff0c;形成自我的架构参考库&#xff0c;按TOGAF开发方法&#xff0c;分别形成标准信息库&#xff08;Standards Information Base&…

【论文通读】SeeClick: Harnessing GUI Grounding for Advanced Visual GUI Agents

SeeClick: Harnessing GUI Grounding for Advanced Visual GUI Agents 前言AbstractMotivationMethodGUI grounding for LVLMsData ConstructionTraining Details ScreenSpotExperimentsGUI Grounding on ScreenSpotVisual GUI Agent TasksMiniWobAITWMind2WebOther experiment…

使用Inno Setup 6制作软件安装包

制作软件安装包的工具非常多&#xff0c;比如SetupFactory、NSIS、Advanced Installer等等&#xff0c;都可以制作不同样式的软件安装包&#xff0c;但是在这些软件里面&#xff0c;Inno Setup最好&#xff0c;原因是他可以定制化个性的安装界面和卸载界面&#xff0c;只是难度…

贪心推公式——AcWing 125. 耍杂技的牛

贪心推公式 定义 贪心算法是一种在每一步选择中都采取在当前状态下最优的选择&#xff0c;希望通过局部的最优选择来得到全局最优解的算法策略。 运用情况 问题具有最优子结构&#xff0c;即一个问题的最优解包含其子问题的最优解。可以通过局部最优决策逐步推导到全局最优…

带百分比的进度条控件(ProgressBar)源码

带百分比的进度条控件&#xff08;ProgressBar&#xff09;&#xff1a; 源码下载地址&#xff1a;https://download.csdn.net/download/wgxds/89472915

48-5 内网渗透 - JuicyPotato、Pipe Potato提权

Juicy Potato Juicy Potato 与 Rotten Potato(烂土豆) 的原理几乎完全相同,只是在后者的基础上做了扩展,以便更灵活地利用 Rotten Potato。Juicy Potato 不再像 Rotten Potato 那样依赖于一个现有的 Meterpreter,并且可以自定义 COM 对象加载的端口,以及根据系统版本更换…

【AWS SMB 能力最佳实践】利用 MGN 解决方案实现跨AWS账号迁移Amazon EC2 实例、弹性IP地址等资源

文章目录 一、实验情景二、实验关键服务概述2.1 MGN解决方案2.2 VPC对等连接 三、实验架构示意图四、实验具体操作步骤4.0 创建访问密钥4.1 创建VPC资源4.1.1 在源账号上创建VPC4.1.2 在目标账号上创建VPC 4.2 创建对等连接✨4.2.1 发起对等连接请求4.2.2 接受对等连接请求4.2.…

vue上传文件拿到File,下载文件到本地

vue中使用upload组件上传pdf文件&#xff0c;拿到File内容后&#xff0c;下载pdf文件到本地vue中根据url下载pdf文件到本地 File文件内容的格式 注意&#xff1a;如果使用iview的upload组件上&#xff0c;要获取File文件&#xff0c;需要在before-upload钩子上获取 async down…

分治精炼宝库----归并排序应用( ´◔︎ ‸◔︎`)

目录 一.基本概念: 二.归并排序&#xff1a; 三.交易逆序对总数&#xff1a; 四.计算右侧小于当前元素的个数&#xff1a; 五.翻转对&#xff1a; 六.合并k个有序链表&#xff1a; 一.基本概念: &#x1f43b;在计算机科学中&#xff0c;分治法是一种很重要的算法。字面上的…

深入理解数据仓库建模——数据湖、数仓一体化

引言 在当今数据驱动的时代&#xff0c;数据仓库和数据湖的结合已经成为企业数据管理的关键。本文将深入探讨数据湖与数据仓库一体化的概念、优势以及实现方法&#xff0c;并结合实际案例&#xff0c;为大家展示如何有效地实现这一目标。 数据湖与数据仓库的区别 数据湖和数…

服务器数据恢复—raid5热备盘同步失败导致阵列崩溃如何恢复数据?

服务器存储数据恢复环境&故障&#xff1a; 某品牌DS5300存储&#xff0c;包含一个存储机头和多个磁盘柜&#xff0c;组建了多组RAID5磁盘阵列。 某个磁盘柜中的一组RAID5阵列由15块数据盘和1块热备硬盘组建。该磁盘柜中的某块硬盘离线&#xff0c;热备盘自动替换并开始同步…

基于YOLOv5+pyqt5的口罩佩戴检测系统(PyQT页面+YOLOv5模型+数据集)

简介 在各种工作环境和公共场所,确保人们正确佩戴口罩对个人防护和公共卫生至关重要,尤其是在医疗设施、制造业车间和拥挤的公共交通中。为了满足这一需求,我们开发了一种基于YOLOv5目标检测模型的口罩佩戴检测系统。本项目不仅实现了高精度的口罩佩戴检测,还设计了一个可…

STM32上实现spwm调制原理分析

在STM32微控制器上实现SPWM&#xff08;正弦脉宽调制&#xff0c;Sinusoidal Pulse Width Modulation&#xff09;调制的核心是利用高频载波&#xff08;三角波&#xff09;与低频基波&#xff08;正弦波&#xff09;作比较得出。 那么在STM32里三角波和正弦波分别是什么&…

在React中,如何利用React.memo函数对函数组件进行优化?

React.memo 是 React 的一个高阶组件&#xff0c;用于对函数组件进行性能优化。它通过记忆化&#xff08;memoization&#xff09;来避免不必要的重新渲染。当组件的 props 没有变化时&#xff0c;React.memo 可以防止组件重新渲染&#xff0c;从而提高应用的性能。 使用 Reac…

DVWA 靶场 SQL Injection (Blind) 通关解析

前言 DVWA代表Damn Vulnerable Web Application&#xff0c;是一个用于学习和练习Web应用程序漏洞的开源漏洞应用程序。它被设计成一个易于安装和配置的漏洞应用程序&#xff0c;旨在帮助安全专业人员和爱好者了解和熟悉不同类型的Web应用程序漏洞。 DVWA提供了一系列的漏洞场…

VSCode 安装Remote-SSH

1、打开扩展商店安装Remote-SSH 快捷键&#xff1a;CtrlShiftX 2、配置ssh连接 打开命令面板&#xff08;CtrlShiftP&#xff09; 输入"Remote-SSH: Connect to Host"并选择。 输入你的Ubuntu服务器的IP地址或主机名。 3、连接到ubuntu服务器 如果是第一次连接&…

GPTCache:革新大模型缓存,降低成本,提升效率

GPTCache介绍 随着应用程序越来越受欢迎并遇到更高的流量水平,与 LLM API 调用相关的费用可能会变得相当可观。此外,LLM 服务的响应时间可能会很慢,尤其是在处理大量请求时。GPTCache是一个致力于构建用于存储 LLM 响应的语义缓存的项目。 项目架构 数字人助力传统客服 1…

Inpaint软件最新版下载【安装详细图文教程】

​根据使用者情况表明在今天的数字时代&#xff0c;我们经常会遇到需要处理图形的情况&#xff0c;然而&#xff0c;当我们遇到水印在图形上&#xff0c;我们就需要寻找一个有效的方式来去除它&#xff0c;Inpaint软件就是一个非常实用的工具&#xff0c;它能够帮助我们去除水印…

数据结构小知识2:树

一、什么是树 数据结构中的树是一种非常重要的非线性数据结构。它由节点&#xff08;Node&#xff09;和边&#xff08;Edge&#xff09;组成&#xff0c;用于表示具有层次关系的数据。 1.1、树的基本概念 节点&#xff08;Node&#xff09;&#xff1a; 树的基本单位&…

修改yarn、npm、pnpm为国内镜像源

国内由于网络的原因&#xff0c;使用官方的npm、yarn、pnpm访问下载依赖库会很慢&#xff0c;有时候还会出现无法访问的情况&#xff0c;这时候就需要我们给npm、yarn、pnpm换一个国内的镜像源的&#xff0c;一般的我们可以将镜像换成淘宝的源&#xff0c;由于平时比较常用到的…