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

news2024/11/19 11:18:39

队列:

  • 线性的集合。
  • 先进先出(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;                   // 实际存储数据个数,初始化为0
	queue->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 queue
	int length;	// maximum number of the queue
	int n;		// actual number of the queue
	int *front;	// point to the first element
	int *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 space
	int *tmp = queue->front;			// copy datas to new memroy space
	if(queue->front < queue->rear)
	{ // copy elements from front pointer to rear pointer
		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++)
		{ // copy elements from front pointer to the end of the queue
			t[i] = *tmp;
			tmp++;
		}
		for(; i < queue->n; i++)
		{ // copy elements from start of the queue to the rear pointer
			t[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 0
	if(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 0
	if(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 pointer
		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++)
		{ // copy elements from front pointer to the end of the queue
			printf("%d  ", *tmp);
			tmp++;
		}
		for(; i < queue->n; i++)
		{ // copy elements from start of the queue to the rear pointer
			printf("%d  ", queue->p[i - m]);
		}
	}
	printf("\n");
}

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

执行可执行文件: ./queue

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

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

相关文章

虚拟机启动失败 请进行修复 关闭hyper-v

场景 win11开启夜神模拟器时弹出此提示。点击关闭hyper-v并重启电脑后仍然不行。 解决方法 关闭 Windows安全中心 的 内存完整性 后重启电脑恢复正常。 补充 由于我这里除了会用到夜神模拟器&#xff0c;还会用到docker&#xff0c;而docker又依赖hyper-v&#xff0c;不…

PHP基础教程——总结W3school

1、<?php ?> 2、$ 声明变量 3、变量大小写敏感 关键字&#xff08;if、else、echo&#xff09;和用户定义的类、函数大小写不敏感 4、三种注释 // # /* */ 5、echo "<br>"; 换行 6、global(关键字) 函数内访问全局变量 $GLOBALS[index] …

三坐标测量机的“柔性”特点及其在工业中的应用

现代制造业中&#xff0c;三坐标测量机&#xff08;CMM&#xff09;在产品开发、质量控制和生产过程中发挥着重要作用。它通过高精度准确测量工件的几何尺寸和形状&#xff0c;来保证产品质量符合严格的技术规范。CMM高精度和高效率的特点使其成为自动化生产线和质量控制流程中…

统一的可观察性和安全性如何增强你的业务?

作者&#xff1a;来自 Elastic Michael Calizo 利用人工智能、异常检测和增强攻击发现功能&#xff0c;在一个平台上增强组织的可观察性和安全性能力 当今数字环境中的组织越来越关注服务可用性&#xff0c;并保护其软件免受恶意篡改和攻击。传统的安全和可观察性工具通常以孤…

SpringMVC的架构有什么优势?——控制器(一)

文章目录 控制器(Controller)1. 控制器(Controller)&#xff1a;2. 请求映射(Request Mapping)&#xff1a;3. 参数绑定(Request Parameters Binding)&#xff1a;4. 视图解析器(View Resolver)&#xff1a;5. 数据绑定(Data Binding)&#xff1a;6. 表单验证(Form Validation)…

阿里云物联网应用层开发:第一部分,项目简介

文章目录 1、物联网应用层简介2、阿里云物联网应用层开发例程主要内容3、需要掌握基础知识 1、物联网应用层简介 应用层是物联网系统的用户界面&#xff0c;它提供了用户与系统交互的接口&#xff0c;这一层是将网络传输层的数据结果以易于理解和使用的方式呈现给用户&#xf…

企业互联网建站源码系统 附带完整的安装代码包以及搭建部署教程

系统概述 企业互联网建站源码吸系统是一款集众多先进功能于一身的建站工具。它提供了丰富的模板和组件&#xff0c;允许企业根据自身需求和品牌形象进行个性化定制&#xff0c;快速搭建出具有独特风格的网站。 代码示例 系统特色功能一览 1.用户友好界面&#xff1a;系统采用…

传感器的静态标定

1.传感器静态标定的基本概念 传感器的静态标定指标主要有线性度、灵敏度、重复性、灵敏度等。 &#xff08;1&#xff09;线性度 线性度是描述传感器静态特性的一个重要指标&#xff0c;以被测输入量处于稳定状态为前提。在规定条件下&#xff0c;传感器校准曲线与拟合直线间…

AI音乐革命:创新的门槛降低与产业未来的挑战

文章目录 每日一句正能量前言整体介绍人机合作AI在音乐创作中的辅助作用人机共同创作的模式实现人机共同创作的可能性伦理和法律考量 伦理道德AI与人类创造力的关系技术发展与人类创造力的平衡社会和文化影响结论 后记AI与音乐的未来交响创新的双刃剑版权与伦理的探讨人机合作的…

Centos7安装Minio笔记

一、Minio概述 Minio是一款开源的对象存储服务器&#xff0c;可以运行在多种操作系统上&#xff0c;包括Linux、Windows和MacOS等。提供一种简单、可扩展、高可用的对象存储解决方案&#xff0c;支持多种数据格式&#xff0c;包括对象、块和文件等。Minio是一款强大、灵活、可…

js基础学习

1、js概述 js是javascript的简称&#xff0c;作用是实现页面和用户的交互 js由浏览器解析运行&#xff0c;不需要编译 js由es基础语法&#xff0c;bom浏览器相关&#xff0c;dom文档操作相关 三大部分组成 2、html引入js <!DOCTYPE html> <html lang"zh-CN&qu…

鸿蒙 DevEcho Studio 查看设备文件

在菜单栏单击View > Tool Windows > Device File Browser&#xff0c;打开Device File Browser。 从下拉列表中选择设备&#xff08;设备需已连接&#xff09;。 选择设备后&#xff0c;显示文件/文件夹列表&#xff0c;可进行以下操作&#xff1a; 右键单击目录…

24 年程序员各岗位薪资待遇汇总(最新)

大家好&#xff0c;我是程序员鱼皮。今天分享 24 年 6 月最新的程序员各岗位薪资待遇汇总。 数据是从哪儿来的呢&#xff1f;其实很简单&#xff0c;BOSS 直聘上有一个免费的薪酬查询工具&#xff0c;只要认证成为招聘者就能直接看&#xff0c;便于招聘者了解市场&#xff0c;…

【操作与配置】Xshell安装使用

Xshell是一款功能强大的远程管理工具&#xff0c;主要用于通过SSH&#xff08;Secure Shell&#xff09;、TELNET等协议连接和管理远程服务器。它支持多种会话管理、脚本编写、端口转发等功能&#xff0c;适合系统管理员和开发者使用。 安装 官网下载&#xff1a;家庭/学校免费…

咖啡消费旺季到来 为何想转让的库迪联营商却越来越多

文 | 智能相对论 作者 | 霖霖 去年还在朝“三年万店”计划狂奔的库迪&#xff0c;今年已出现明显“失速”。 早在今年2月&#xff0c;库迪就官宣其门店数已超过7000家&#xff0c;如今4个多月过去&#xff0c;据极海品牌监测数据显示&#xff0c;截至6月27日&#xff0c;其总…

【日记】度过了一个堕落的周末……(184 字)

正文 昨天睡了一天觉&#xff0c;今天看了一天《三体》电视剧。真是堕落到没边了呢&#xff08;笑。本来想写代码完成年度计划&#xff0c;或者多写几篇文章&#xff0c;但实在不想写&#xff0c;也不想动笔。 感觉这个周末什么都没做呢&#xff0c;休息倒是休息好了。 今天 30…

GP37-S-N、GP37-S-E、GP37-S-R比例电磁铁驱动放大器

比例阀用电磁铁EP45-C、EP37-E、EP45-G、EP45-N、GP37-3-A、GP37-S-N、GP37-S-E、GP37-S-R在直流12V/24V的电液比例控制系统中与BEUEC比例控制放大器配套使用&#xff0c;共同作用于比例阀的控制。电磁铁输出力通过负载弹簧转换成位移&#xff0c;实现电流-力-位移线性转换&…

Unity开箱即用的UGUI面板的拖拽移动功能

文章目录 &#x1f449;一、背景&#x1f449;二、效果图&#x1f449;三、原理&#x1f449;四、核心代码&#x1f449;五&#xff0c;总结 &#x1f449;一、背景 之前做PC项目时常常有面板拖拽移动的需求&#xff0c;今天总结封装一下&#xff0c;做成一个随时随地可复用的…

Web工程化

1、webpack 1.1 概念 一个前端打包器。 webpack 只识别javascript. 所以需要安装nodejs环境。 1.2 运行环境 Nodejs Nodejs 是运行JavaScript的环境。 因为nodejs发布了许多版本&#xff0c;在不同的技术栈下&#xff0c;需要使用不同的nodejs。 所以需要在电脑上安装n…

鸿蒙应用更新跳转到应用市场

鸿蒙没有应用下载安装&#xff0c;只支持跳转到应用市场更新 gotoMarket(){try {const request: Want {parameters: {// 此处填入要加载的应用包名&#xff0c;例如&#xff1a; bundleName: "com.huawei.hmsapp.appgallery"bundleName: com.huawei.hmos.maps.app}}…