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

2024-06-24 04:52

本文主要是介绍数据结构和算法(1) ---- Queue 的原理和实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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 elementif(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;
}

这篇关于数据结构和算法(1) ---- Queue 的原理和实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089220

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja