【算法与数据结构】队列

news2024/10/6 12:28:10

队列

队列:结构定义

队列是有一篇连续的存储区,其实连续性不重要,而是队列需要保持一个特性:
从队首出元素,从队尾入元素。这一点与顺序表不一样,元素加入的位置不一样
队列:只允许从尾部加入元素,从头部去除元素
顺序表:允许在任意位置加入或者删除元素
队列的属性
size, 记录队列的总大小
head, 指向队首的指针, 包含队首
tail,指向队尾的指针,不包含队尾
先进先出,first in - first out(FIFO)

在这里插入图片描述

队列:出队(Pop)

队列只允许从队首出队
在这里插入图片描述
在这里插入图片描述

队列:入队(Push)

只允许从队尾入队
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

队列:假溢出

最简单的队列是有问题的
假设入队了7, 8, 9三个元素,要入队10号元素
队列已经“满了”,入不了队
实际上只存储了6个元素,但队列的总大小是9
在这里插入图片描述
提出一种新的队列结构:循环队列
当tail超出范围的时候,就让tail指向0号位置
在这里插入图片描述

队列:循环队列

当tail超出范围的时候,就让tail指向0号位置
多了一个属性项:
count: 记录的是队列中当前一共存放了多少个元素
在这里插入图片描述
入队:
在这里插入图片描述
循环队列是为了解决队列的假溢出问题

队列:顺序表的实现

队列结构定义: typedef struct Queue{}Queue;

// 队列
typedef struct Queue{
	Vector * data;
	int size, head, tail, count;  // 循环队列

}Queue;

初始化: int * initQueue(int n) {}, 其中使用了顺序表的初始化函数initVector()

// 初始化
Queue * initQueue(int n)
{
	Queue *q = (Queue *)malloc(sizeof(Queue));
	q->data = initVector(n);    // 用顺序表去初始化
	q->size = n;
	q->head = q->tail = q->count = 0;
	return q;
}

判空操作: int empty(Queue *q) {}

// 判空操作
int empty(Queue *q)
{

	return q->count == 0;
}

查看队首元素: int frontQueue(Queue *q) {}, 其中用到了顺序表的查找操作vectorSeek()函数

// 查看队首元素
int frontQueue(Queue *q)
{
	return vectorSeek(q->data, q->head);    // vectorSeek(data, i), 得到顺序表data的第i个元素
}

压入队列: int push(Queue *q, int val) {}, 其中用到了顺序表的插入操作insertVector()函数

// 压入队列
int push(Queue *q, int val)
{
	if (q->size == q->count) return 0;
	// 把val放到tail所指向的位置
	insertVector(q->data, q->tail, val);
	q->tail += 1;
	// 判断tail是否指向非法位置
	if (q->tail == q->size) q->tail = 0;   // 队满了后让tail重新指向队首
	q->count += 1;

	return 1;
}

弹出队列: int pop(Queue *q) {}

// 弹出队列
int pop(Queue *q)
{
	if (empty(q)) return 0;
	eraseVector(q->data, q->head); // 删掉head指向的元素
	
	q->head += 1;
	//判断head是否越界
	if (q->head == q->size) q->head = 0; // head重新指向队首

	q->count -= 1;
	return 1;
	
}

**销毁:**void clearQueue(Queue *q) {},其中用到了顺序表的销毁函数clearVector()

// 销毁
void clearQueue(Queue *q)
{
	if (q == NULL) return;
	clearVector(q->data);
	free(q);
	return;

}

下面实现顺序表:
顺序表结构定义: typedef struct Vector{}Vector;

// 顺序表
typedef struct Vector{
	int size, count;
	int *data;
} Vector;

初始化顺序表: Vector * initVector(int n) {}

// 初始化
Vector * initVector(int n)
{
	Vector *v = (Vector *)malloc(sizeof(Vector));
	v->data = (int *)malloc(sizeof(int)* n);
	v->size = n;
	v->count = 0;
	return v;
}

查找顺序表: int vectorSeek(Vector *v, int pos) {}

// 查找顺序表
int vectorSeek(Vector *v, int pos)
{
	if (pos < 0 || pos >= v->size) return -1;
	if (v->count > 0) return v->data[pos];
	return 0;
	
}

插入元素: int insertVector(Vector *v, int pos, int val)

// 插入元素
int insertVector(Vector *v, int pos, int val)
{
	if (pos < 0 || pos >= v->size) return 0;
	// 由于pos只能在队尾插入,只要挪一位就行
	v->data[pos] = val;
	v->count += 1;
	return 1;
	
}

删除元素: int eraseVector(Vector *v, int pos) {}


// 删除元素
int eraseVector(Vector *v, int pos)
{
	if (pos < 0 || pos >= v->size) return 0;
	v->data[pos] = 0;
	v->count -= 1;
	return 1;
}

销毁顺序表: void clearVector(Vector *v){}

// 销毁顺序表
void clearVector(Vector *v)
{
	if (v == NULL) return;
	free(v->data);
	free(v);
	return;
}

主程序:

void outputQueue(Queue *q)
{
	printf("Queue:  ");
	for (int i = 0; i < q->count; i++)
	{
		printf("%4d ", vectorSeek(q->data, (q->head + i) % q->size));
	}
	printf("\n\n");
}



int main()
{
	srand(time(0));
    #define MAX_OP 10
	Queue *q = initQueue(MAX_OP);
	for (int i = 0; i < MAX_OP; i++)
	{
		int op = rand() % 5, val = rand() % 100;    // 0, 1: pop;  2, 3, 4: push
		switch (op)
		{
		case 0:
		case 1:
			// 出队列之前查看一下队首元素
			printf("front of queue: %d\n", frontQueue(q));
			pop(q);
			break;
		case 2:
		case 3:
		case 4:
			printf("push %d to queue\n", val);
			push(q, val);
			break;


		}
		outputQueue(q);
	}

	clearQueue(q);

	std::cin.get();
	return 0;

}

测试结果

在这里插入图片描述

队列:链表的实现

队列的结构定义: typedef struct Queue{}Queue;
使用链表实现,不在乎存储空间的大小,也就不存在队列假溢出的问题,实际上也不需要头尾指针了,但是还是可以记录一个count

typedef struct Queue{
	LinkList * l;
	int count;

} Queue;

初始化队列: Queue *initQueue() {}

Queue *initQueue()
{
	Queue *q = (Queue*)malloc(sizeof(Queue));
	q->count = 0;
	q->l = initLinkList();
	return q;

}

判空操作: int empty(Queue *q) {}

// 判空操作
int empty(Queue *q)
{
	return q->count == 0;
}

查看队首元素: int frontQueue(Queue *q) {}

// 查看队首元素
int frontQueue(Queue *q)
{
	if (empty(q)) return 0;
	return frontLinkList(q->l);
}

压入队列: int push(Queue *q, int val) {}
不用判断队列是否满了,直接入队操作

// 压入队列
int push(Queue *q, int val)
{
	// 不用判断队列是否满了,直接入队操作
	insertTail(q->l, val);
	q->count += 1;
	return 1;
}

弹出队列: int pop(Queue *q) {}

// 弹出队列
int pop(Queue *q)
{
    if (empty(q)) return 0;
	eraseHead(q->l);
	q->count -= 1;
	return 1;
}

销毁队列: void clearQueue(Queue *q) {}

void clearQueue(Queue *q)
{
	if (q == NULL) return;
	clearLinkList(q->l);
	free(q);
	return;
}

下面实现链表:
链表节点定义: typedef struct Node{ } Node;

typedef struct Node{
	int data;
	Node * next;
} Node;

链表结构定义: typedef struct LinkList{ } LinkList;

// 链表结构定义
typedef struct LinkList{
	Node head, *tail;  // 有头链表

}LinkList;

表节点的初始化: Node *getNewNode(int val) {}

// 链表节点的初始化
Node *getNewNode(int val)
{
	Node *p = (Node *)malloc(sizeof(Node));
	p->data = val;
	p->next = NULL;
	return p;
}

初始化链表: LinkList * initLinkList() {}

// 初始化链表
LinkList * initLinkList()
{
	LinkList *l = (LinkList *)malloc(sizeof(LinkList));
	l->head.next = NULL;
	l->tail = &(l->head);
	return l;
	
}

判空操作: int emptyList(LinkList *l) {}

// 判空操作
int emptyList(LinkList *l)
{
	return l->head.next == NULL;
}

查找队首元素: int frontLinkList(LinkList *l) {}

// 查找队首元素
int frontLinkList(LinkList *l)
{
	if (emptyList(l)) return 0;

	return l->head.next->data;             //返回
}

链表尾部插入元素: int insertTail(LinkList *l, int val) {}

// 在链表尾部插入元素
int insertTail(LinkList *l, int val)
{
	Node *node = getNewNode(val);  // 封装成链表的节点
	// 节点添加到链表尾部
	l->tail->next = node;
	l->tail = node;

	return 1;
}

删掉链表头节点: int eraseHead(LinkList *l) {}

// 删掉链表头节点
int eraseHead(LinkList *l)
{
	if (emptyList(l)) return 0;
	Node *p = l->head.next;
	l->head.next = p->next;

	// 还需要考虑只有一个节点的情况,此时tail指向这个节点,要将tail指向head
	if (p == l->tail) l->tail = &(l->head);
	free(p);
	return 1;
}

销毁链表: void clearLinkList(LinkList *l) {}


// 销毁链表
void clearLinkList(LinkList *l)
{
	Node *p = l->head.next, *q;
	// 先销毁头节点后面的所有节点
	while (p)
	{
		q = p->next;  // 用q记录p的下一个节点
		free(p);
		p = q;
	}

	free(l);
	return;
}

主程序:

// 输出队列
void outputQueue(Queue *q)
{
	printf("Queue:  ");
	// 用一个p指针来遍历链表
	Node *p = q->l->head.next;
	for (int i = 0; i < q->count; i++)
	{
		printf("%4d", p->data);
		p = p->next;
	}
	printf("\n\n");
}



int main()
{
	srand(time(0));
    #define MAX_OP 10
	Queue *q = initQueue();
	for (int i = 0; i < MAX_OP; i++)
	{
		int op = rand() % 5, val = rand() % 100;    // 0, 1: pop;  2, 3, 4: push
		switch (op)
		{
		case 0:
		case 1:
			// 出队列之前查看一下队首元素
			printf("front of queue: %d\n", frontQueue(q));
			pop(q);
			break;
		case 2:
		case 3:
		case 4:
			printf("push %d to queue\n", val);
			push(q, val);
			break;


		}
		outputQueue(q);
	}

	clearQueue(q);

	std::cin.get();
	return 0;

}

测试结果

在这里插入图片描述

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

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

相关文章

P1003 [NOIP2011 提高组] 铺地毯

题目提供者 CCF_NOI 难度 普及- 此篇必须看到底&#xff01; 题目描述 为了准备一个独特的颁奖典礼&#xff0c;组织者在会场的一片矩形区域&#xff08;可看做是平面直角坐标系的第一象限&#xff09;铺上一些矩形地毯。一共有 n 张地毯&#xff0c;编号从 1 到 n。现在…

电力物联网是什么?在智能配电系统中有什么作用?

摘要&#xff1a;在社会经济和科学技术不断发展中&#xff0c;配电网实现了角色转变&#xff0c;传统的单向供电服务形式已经被双向能流服务形式取代&#xff0c;社会多样化的用电需求也得以有效满足。随着物联网技术的发展&#xff0c;泛在电力物联网开始应用于当今的电力系统…

便携式挂钩型儿童椅 标准ASTMF1235测试项目周期多久?

便携式挂钩型儿童椅 适用于6 个 月至 3 岁之间的儿童&#xff0c;体重不超过 37 磅&#xff0c;并具 备自主协调坐姿的能力。 那么该类产品上亚马逊需要做下面的检测&#xff1a; 便携式儿童外出餐椅 ASTM F1235-18 和 CPSIA&#xff08;铅、邻苯二甲酸盐&#xff09; 亚马逊…

新手开始学【网络安全】要怎么入门?

前言&#xff1a;网络安全如何从零开始学习&#xff0c;少走弯路&#xff1f; 目录&#xff1a; 一&#xff0c;怎么入门&#xff1f; 1、Web 安全相关概念&#xff08;2 周&#xff09;2、熟悉渗透相关工具&#xff08;3 周&#xff09;3、渗透实战操作&#xff08;5 周&…

M304A-ZN-当贝纯净桌面-卡刷固件包-内有教程

M304A-ZN-当贝纯净桌面-卡刷固件包-内有教程 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&#xff1b; 4、大量精简内置的没用的软件&#xff0c;运行速度提升…

用ChatGPT三分钟免费做出数字人视频- 提升自媒体魅力

用ChatGPT三分钟免费做出数字人视频- 提升自媒体魅力 一、ChatGPT产生文案二、腾讯智影网站三、选择一个2D数字人四、粘贴文本五、编辑自定义&#xff0c;合成六、资源七、其他数字人平台推荐八、生成视频预览 本教程收集于&#xff1a;AIGC从入门到精通教程汇总 操作指引 Ch…

KingbaseES V8R3 集群运维系列 -- sync_flag参数配置

​案例说明&#xff1a; 在KingbaseES V8R3集群一主二备的架构中&#xff0c;配置了流复制为同步(sync)模式&#xff0c;但是集群启动后&#xff0c;流复制状态中显示备库是async模式(备库和主库数据已经同步)&#xff0c;从备库的recovery.log日志也可以看到&#xff0c;备库启…

记录--前端实现点击选词功能

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 今天有一个需求&#xff0c;点击选中某个英文单词&#xff0c;然后对这个单词做一些处理&#xff0c;例如高亮背景、查看一些详细信息等等&#xff0c;今天简单实现了一下&#xff0c;效果如下&#x…

ChatGLM-6B本地cpu部署

ChatGLM-6B是清华团队研发的机器人对话系统&#xff0c;类似ChatGPT&#xff0c;但是实际相差很多&#xff0c;可以当作一个简单的ChatGPT。 ChatGLM部署默认是支持GPU加速&#xff0c;内存需要32G以上。普通的机器无法运行。但是可以部署本地cpu版本。 本地部署&#xff0c;需…

ePWM模块(3)

比较模块 CMPA:比较寄存器A,其值与TBCTR值比较,相同时,事件发送到动作模块。 CMPB:比较寄存器B,其值与TBCTR值比较,相同时,事件发送到动作模块。 CMPCTL:控制寄存器(重要) SHDWAFULL(或SHDWBFULL):CMPA(或B)阴影寄存器满标志位 0:未满 1:满了 SHDWAMODE(或…

【致敬未来的攻城狮计划】— 连续打卡第二十六天:瑞萨RA Cortex-M 内核RA2E1 RT-Thread BSP 启蒙知识

系列文章目录 由于一些特殊原因&#xff1a; 系列文章链接&#xff1a;&#xff08;其他系列文章&#xff0c;请点击链接&#xff0c;可以跳转到其他系列文章&#xff09;或者参考我的专栏“ 瑞萨MCU ”&#xff0c;里面是 瑞萨RA2E1 系列文章。 24.RA2E1的 DMAC——数据传输 …

Ubuntu设置静态IP地址的方法

今天重装了ubuntu22.04server系统&#xff0c;顺便将Ip方法的配置方法记录下&#xff0c;备存。 步骤1&#xff1a;先ifconfig查看电脑的网卡信息 找到物理网卡的名称&#xff0c;我这里是enp3s0 步骤2&#xff1a;找到gateway网关地址 输入route -n命令&#xff0c;打印路由…

数据知识驱动的城市作战元宇宙建模框架

源自&#xff1a;指挥与控制学报 作者&#xff1a;郑文博 李强 刘文礼 费爱国 王飞跃 摘 要 1 相关工作与问题提出 2 新型元宇宙框架的构建 图 1 平行智能与元宇宙 图2 数据知识驱动的城市作战元宇宙建模框架 3 案例设计 3.1 基于生成式对抗网络的表现力改进设计 图…

开关电源基础06:基本开关电源电感能量传输原理

说在开头&#xff1a;关于第六届索尔维会议&#xff08;1&#xff09; 1930年&#xff0c;第六届的索尔维会议要召开了&#xff0c;一大帮子物理学家又在深秋时节聚到了布鲁塞尔&#xff1b;玻尔来到会场时心中踹踹不安&#xff0c;看爱因斯坦似笑非笑的表情&#xff0c;吃不准…

这所院校23年分数线暴涨45分,临时扩招69人!!

本期为大家整理热门院校-“南京信息工程大学”的择校分析&#xff0c;这个择校分析专题会为大家结合&#xff1a;初试复试占比、复试录取规则&#xff08;是否公平&#xff09;、往年录取录取名单、招生人数、分数线、专业课难度等进行分析。希望能够帮到大家! –所有数据来源…

关于【SD-WEBUI】的API:开发代码示例和帮助文档

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;启用API&#xff08;二&#xff09;编写调用程序&#xff08;2.1&#xff09;Python例子代码&#xff08;2.2&#xff09;执行&#xff08;2.3&#xff09;结果 &#xff08;三&#xff09;帮助文档&#xf…

第7章 动静分离

第7章 动静分离 Nginx的负载均衡和静态代理结合在一起&#xff0c;我们可以实现动静分离&#xff0c;这是实际应用中常见的一种场景。 动态资源&#xff0c;如jsp由tomcat或其他web服务器完成 静态资源&#xff0c;如图片、css、js等由nginx服务器完成 它们各司其职&#x…

苹果备忘录永久删除了怎么办?3种备忘录恢复的方法!

案例&#xff1a;iPhone备忘录彻底删除了怎么办&#xff1f; 【友友们&#xff0c;苹果备忘录永久删除了&#xff0c;还可以恢复吗&#xff1f;有什么方法&#xff1f;】 苹果备忘录是苹果系统自带的一款备忘录应用&#xff0c;可以帮助我们记录日程安排、备忘事项、重要信息等…

深度学习技巧应用13-神经网络中数据并行训练的原理

大家好,我是微学AI,今天给大家介绍一下人工智能基础部分15-神经网络中数据并行训练的原理,在神经网络中,数据并行训练是一种常用的训练技术。它利用多个GPU或多个计算机对同一个模型进行训练,不同的设备处理相同的模型和数据,但会随机选择不同的批次数据,并使用反向传播…

视频创作教程-蜜蜂剪辑软件

视频创作教程-蜜蜂剪辑软件 作者介绍 一、视频剪辑软件二、蜜蜂剪辑软件使用1.视频比例选择2.添加视频素材3.视频分割4.添加文字5.转场滤镜6.其它 三、创作实例四、软件分享 作者介绍 熊文博&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2020级硕士研究生&…