【数据结构】(C语言):队列

队列:

  • 线性的集合。
  • 先进先出(FIFO,first in first out)。
  • 两个指针:头指针(指向第一个进入且第一个出去的元素),尾指针(指向最后一个进入且最后一个出去的元素)。
  • 两个操作:入队(往队尾添加元素),出队(从队头删除元素)。
  • 队列有优先队列,双端队列,循环队列等。
  • 可以使用链表实现,也可以使用数组实现。本文使用数组实现循环队列。

添加元素:

往队尾添加。若尾指针已指向队尾,则循环重新指向队头。

删除元素:

从队头删除。若头指针已指向队尾,则循环重新指向队头。

扩容、缩容:

若内存区域已全部使用完,则增加内存区域。若内存区域使用小,则减少内存区域。

方法:新开辟内存区域,将原数据复制到新内存区域。

若头指针在尾指针的前面,则从头指针到尾指针的数据依次复制到新内存区域。

若尾指针在头指针的前面,则从头指针到内存区域最后的这m个数据,依次复制到新区域0到m-1,再从0到尾指针的数据,依次复制到n到n-1(n为实际存储数据个数)。

 ​​​​​​


C语言实现:(使用数组实现循环队列)

创建结构体数据类型:

  • 指针p:记录数组的内存地址(即数组第一个元素的地址)。
  • 整型length:记录数组最大物理容量(即创建数组时指定的内存大小)。
  • 整型n:记录数组实际逻辑大小(即数组实际已经存储的数据个数)。
  • 指针front:头指针,始终指向数组数据中第一个进入且将第一个出去的元素。
  • 指针rear:尾指针,始终指向数组数据中最后一个进入且将最后一个出去的元素。
typedef struct Queue
{int *p;		    // 数组内存地址int length;	    // 物理最大容量int n;		    // 实际存储数据int *front;	    // 始终指向第一个进入且第一个出去的元素int *rear;	    // 始终指向最后一个进入且最后一个出去的元素
} Queue;	        // 别名

创建队列变量:

Queue queue;

初始化队列:

void init(Queue *queue, int len)
{queue->p = (int *)malloc(len * sizeof(int));     // 分配数组内存空间if(queue->p == NULL){perror("Memory allocation failled");exit(-1);}queue->length = len;            // 指定物理大小queue->n = 0;                   // 实际存储数据个数,初始化为0queue->front = queue->p;        // 头指针,初始化指向数组第一个元素地址queue->rear = queue->p;         // 尾指针,初始化指向数组第一个元素地址
}

扩容、缩容:

void resize(Queue *queue, int len)
{// 开辟新内存空间,将原数据复制到新地址int *t = (int *)malloc(len * sizeof(int));int *tmp = queue->front;// 若头指针在前,依次复制从头指针到尾指针的数据if(queue->front < queue->rear){for(int k = 0; k < queue->n; k++){t[k] = *tmp;tmp++;} }// 若尾指针在前,复制头指针到数组最后的数据,再复制数组开头到尾指针的数据else if(queue->front > queue->rear){int i;int m = queue->p + queue->n - queue->front;for(i = 0; i < m; i++){t[i] = *tmp;tmp++;}for(; i < queue->n; i++){t[i] = queue->p[i - m];}}queue->p = t;queue->length = len;queue->front = queue->p;queue->rear = queue->p + queue->n - 1;
}

 添加元素:

往队尾添加。尾指针rear指向下一个元素。若尾指针已指向区域最后,则尾指针循环重新指向区域开头。

void add(Queue *queue, int data)
{if(queue->length == queue->n)	// 若数组满,扩容{int newlength = queue->length * 2;resize(queue, newlength);}// 若尾指针指向数组最后,尾指针循环开始指向数组开头if(queue->rear == queue->p + queue->n) queue->rear = queue->p;else queue->rear++;*queue->rear = data;queue->n++;
}

删除元素:

从队头删除。头指针front指向下一个元素。若头指针已指向区域最后,则头指针循环重新指向区域开头。

int deltop(Queue *queue)
{int value = *queue->rear;queue->n--;// 若头指针已指向数组尾部,头指针循环开始指向数组开头if(queue->front == queue->p + queue->n)	queue->front = queue->p;else queue->front++;if(queue->n < ceil(queue->length / 2) && queue->length > 4)	// 满足条件,缩容{int newlength = ceil(queue->length / 2);resize(queue, newlength);}return value;
}

遍历队列元素:

void travel(Queue *queue)
{if(queue->n == 0) return ;printf("elements: ");int *tmp = queue->front;// 若头指针在前,依次从头指针遍历到尾指针if(queue->front < queue->rear){for(int k = 0; k < queue->n; k++){printf("%d  ", *tmp);tmp++;} }// 若尾指针在前,遍历头指针到数组最后,再遍历数组开头到尾指针else if(queue->front > queue->rear){int i;int m = queue->p + queue->n - queue->front;for(i = 0; i < m; i++){printf("%d  ", *tmp);tmp++;}for(; i < queue->n; i++){printf("%d  ", queue->p[i - m]);}}printf("\n");
}


完整代码:(queue.c)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>/* structure */
typedef struct Queue
{int *p;		// memory address of the queueint length;	// maximum number of the queueint n;		// actual number of the queueint *front;	// point to the first elementint *rear;	// point to the end element
} Queue;/* function prototype */
void init(Queue *, int);	// queue initialization
void resize(Queue *, int);	// increase or reduce the size of the queue
void add(Queue *, int);         // add element to the end of the queue
int deltop(Queue *);		// delete element from the start of the queue
void travel(Queue *);		// show element one by one/* main function */
int main(void)
{Queue queue;init(&queue, 4);printf("length is %d, actual is %d\n", queue.length, queue.n);add(&queue, 8);add(&queue, 16);add(&queue, 23);printf("length is %d, actual is %d\n", queue.length, queue.n);travel(&queue);add(&queue, 65);printf("length is %d, actual is %d\n", queue.length, queue.n);travel(&queue);add(&queue, 27);     // 已满,扩容printf("length is %d, actual is %d\n", queue.length, queue.n);travel(&queue);deltop(&queue);printf("length is %d, actual is %d\n", queue.length, queue.n);travel(&queue);deltop(&queue);      // 使用少于一半,缩容printf("length is %d, actual is %d\n", queue.length, queue.n);travel(&queue);deltop(&queue);deltop(&queue);deltop(&queue);printf("length is %d, actual is %d\n", queue.length, queue.n);return 0;
}/* subfunction */
void init(Queue *queue, int len)		// queue initialization
{queue->p = (int *)malloc(len * sizeof(int));if(queue->p == NULL){perror("Memory allocation failled");exit(-1);}queue->length = len;queue->n = 0;queue->front = queue->p;queue->rear = queue->p;
}void resize(Queue *queue, int len)	// increase or reduce the size of the queue
{int *t = (int *)malloc(len * sizeof(int));	// new memory spaceint *tmp = queue->front;			// copy datas to new memroy spaceif(queue->front < queue->rear){ // copy elements from front pointer to rear pointerfor(int k = 0; k < queue->n; k++){t[k] = *tmp;tmp++;} }else if(queue->front > queue->rear){int i;int m = queue->p + queue->n - queue->front;for(i = 0; i < m; i++){ // copy elements from front pointer to the end of the queuet[i] = *tmp;tmp++;}for(; i < queue->n; i++){ // copy elements from start of the queue to the rear pointert[i] = queue->p[i - m];}}queue->p = t;queue->length = len;queue->front = queue->p;queue->rear = queue->p + queue->n - 1;
}void add(Queue *queue, int data)        // add element to the end of the queue
{if(queue->length == queue->n)	// increase the size of the queue{int newlength = queue->length * 2;resize(queue, newlength);}// if rear point to the end space, rear point to index 0if(queue->rear == queue->p + queue->n) queue->rear = queue->p;else queue->rear++;*queue->rear = data;queue->n++;
}int deltop(Queue *queue)		// delete element from the start of the queue
{int value = *queue->rear;queue->n--;// if front point to the end space,front point to index 0if(queue->front == queue->p + queue->n)	queue->front = queue->p;else queue->front++;if(queue->n < ceil(queue->length / 2) && queue->length > 4)	// reduce the size of the queue{int newlength = ceil(queue->length / 2);resize(queue, newlength);}return value;
}void travel(Queue *queue)		// show element one by one
{if(queue->n == 0) return ;printf("elements: ");int *tmp = queue->front;if(queue->front < queue->rear){ // copy elements from front pointer to rear pointerfor(int k = 0; k < queue->n; k++){printf("%d  ", *tmp);tmp++;} }else if(queue->front > queue->rear){int i;int m = queue->p + queue->n - queue->front;for(i = 0; i < m; i++){ // copy elements from front pointer to the end of the queueprintf("%d  ", *tmp);tmp++;}for(; i < queue->n; i++){ // copy elements from start of the queue to the rear pointerprintf("%d  ", queue->p[i - m]);}}printf("\n");
}

编译链接: gcc -o queue queue.c

执行可执行文件: ./queue

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

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

相关文章

Linux CentOS 7 离线安装.NET环境

下载 下载.NET 例如&#xff1a; aspnetcore-runtime-6.0.15-linux-x64.tar.gz 复制 复制到如下目录&#xff1a; /usr/local/dotnet/aspnetcore-runtime-6.0.15-linux-x64.tar.gz 解压 cd /usr/local/dotnet/ tar -zxvf aspnetcore-runtime-6.0.15-linux-x64.tar.gz 创建…

Linux开发讲课29---Linux USB 设备驱动模型

Linux 内核源码&#xff1a;include\linux\usb.h Linux 内核源码&#xff1a;drivers\hid\usbhid\usbmouse.c 1. BUS/DEV/DRV 模型 "USB 接口"是逻辑上的 USB 设备&#xff0c;编写的 usb_driver 驱动程序&#xff0c;支持的是"USB 接口"&#xff1a; US…

http.cookiejar.LoadError: Cookies file must be Netscape formatted,not JSON.解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

从直播消息中找到对应的proto协议内容

这么多直播间的消息&#xff0c;我们该怎么从里面找到我们需要的消息定义呢&#xff1f; 其实只要你能找到这个里面的this对象&#xff0c;就可以看到这个对象上面有一个root > webcast > im 这里面的函数就都是用于解析直播间消息的函数&#xff1a; 想要看一下每个消息…

短信API的集成过程步骤?有哪些注意事项?

短信API的安全性如何保障&#xff1f;怎么优化API接口的性能&#xff1f; 在现代通信和业务流程中&#xff0c;短信API的使用变得越来越普遍。短信API为企业提供了一种高效、可靠的方式来向客户发送信息。AoKSend将详细介绍短信API的集成过程步骤&#xff0c;帮助企业顺利实施…

2024.07使用gradle上传maven组件到central.sonatype,非常简单

本文基于sonatypeUploader2.0版本 在1.0版本我们还需要手动去添加maven-publish和signing插件&#xff0c;在2.0版本他已经内置了&#xff0c;如果你仍然需要手动配置&#xff0c;你可以手动添加这两个插件及逻辑。 具体信息参考开源仓库&#xff1a; 插件仓库&#xff1a;h…

一个时代的结束:Centos7将在6月30日退出历史舞台

友情提醒&#xff1a; 如果你使用的是曾经辉煌一时的CentOS Linux 7&#xff0c;一直拖延没有迁移&#xff0c;那么现在距离它正式寿终正寝还有不到一周的时间。 CentOS Linux 7 的结束日期仍定在2024年6月30日。红帽早在 2020 年就做出了有争议的举动&#xff0c;将重点转移到…

【人工智能学习之图像操作(一)】

【人工智能学习之图像操作&#xff08;一&#xff09;】 图像读写创建图片并保存视频读取色彩空间与转换色彩空间的转换通道分离理解HSV基本图形绘制 阀值操作OTSU二值化简单阀值自适应阀值 图像读写 图像的读取、显示与保存 import cv2 img cv2.imread(r"1.jpg")…

面试突击:ConcurrentHashMap 源码详解

本文已收录于&#xff1a;https://github.com/danmuking/all-in-one&#xff08;持续更新&#xff09; 前言 哈喽&#xff0c;大家好&#xff0c;我是 DanMu。这篇文章想和大家聊聊 ConcurrentHashMap 相关的知识点。严格来说&#xff0c;ConcurrentHashMap 属于java.lang.cur…

springboot+vue 开发记录(八) 前端项目打包

本篇文章涉及到前端项目打包的一些说明 我打包后的项目在部署到服务器上后&#xff0c;访问页面时按下F12出现了这种情况&#xff1a; 它显示出了我的源码&#xff0c;这是一种很不安全的行为 该怎么办&#xff1f;很简单&#xff1a; 我们只需要下载一点点插件&#xff0c;再…

鸿蒙开发Ability Kit(程序框架服务):【声明权限】

声明权限 应用在申请权限时&#xff0c;需要在项目的配置文件中&#xff0c;逐个声明需要的权限&#xff0c;否则应用将无法获取授权。 在配置文件中声明权限 应用需要在module.json5配置文件的[requestPermissions]标签中声明权限。 属性说明取值范围name必须&#xff0c;…

Python中爬虫编程的常见问题及解决方案

Python中爬虫编程的常见问题及解决方案 引言&#xff1a; 随着互联网的发展&#xff0c;网络数据的重要性日益突出。爬虫编程成为大数据分析、网络安全等领域中必备的技能。然而&#xff0c;爬虫编程不仅需要良好的编程基础&#xff0c;还需要面对着各种常见的问题。本文将介绍…

服装分销的系统架构

背景 服装的分销规则&#xff1a;组织结构由总公司代理商专卖店构成。总公司全权负责销售业务&#xff0c;并决定给代理商的份额&#xff1b;代理商再给货到专卖店&#xff0c;整个组织机构呈现树状结构&#xff1b;上级机构对下级机构拥有控制权&#xff0c;主要控制其销售的服…

LCD 显示--lvds

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

鸿蒙生态应用开发白皮书V3.0

来源&#xff1a;华为&#xff1a; 近期历史回顾&#xff1a;

鸿蒙:this传递参数到子组件中无法实现

this指代当前组件的某个变量&#xff0c;当把这个变量当作参数传递给子组件时&#xff0c;子组件中没有这个变量&#xff0c;属于使用不了这个变量 解决方法&#xff1a;在变量后面加.bind(this)将当前组件的变量一起绑定过去

【6.26更新】Win10 22H2 19045.4598镜像:免费下载!

当前微软已经发布了六月最新的KB5039299更新补丁&#xff0c;用户完成升级后&#xff0c;系统版本号将更新至19045.4598。此次更新解决了任务栏上应用跳转列表失败、可能导致系统无法从休眠状态恢复等多个问题&#xff0c;推荐大家升级。如果您不知道去哪里才能下载到该版本&am…

JavaScript原型对象和对象原型、原型继承、原型链

目录 1. 原型对象和对象原型2. 原型继承3. 原型链 1. 原型对象和对象原型 作用: 以前通过构造函数实例化的对象&#xff0c;每个实例化的对象的属性和方法都是独立的&#xff0c;会造成内存浪费。通过prototype对象原型能实现不同实例化对象共享公用的属性和方法&#xff0c;减…

STM32之四:TIM定时器(1-基本定时器)

目录 1. STM32有哪些定时器 2. 基本定时器 2.1 基本定时器主要功能 2.2 基本定时器的框图 2.2.1 时钟输入 2.2.2 至DAC 2.2.3 至时基单元&#xff08;重点&#xff09; 2.2.4 影子寄存器 2.2.5 基本定时器寄存器说明 2.2.5.1 控制寄存器1&#xff08;TIMx_CR1&#x…

ITK-二值阈值分割

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 什么是二值阈值分割&#xff1f; 二值阈值分割是一种常见的图像处理技术&#xff0c;用于将图像的像素值分成两个类别&#xff1…