优先队列C

由于看到P1629 邮递员送信这题,就去学了优先队列.为学习Dijkstra算法做准备

什么是优先队列

优先队列:是一种特殊类型的队列,每个元素都有一个相关的优先级。在优先队列中,元素按照优先级的顺序进行排列,具有最高(或最低)优先级的元素会最先被删除或访问。

想实现优先队列可以先去学习堆排序,优先队列利用的就是堆排序这个原理,所以下面先介绍一下堆排序

什么是堆排序

堆排序是一种基于二叉堆数据结构的排序算法,它的主要思想是利用堆这种数据结构的特性来进行排序。

堆是一个完全二叉树,同时具有最大堆(左图)和最小堆(右图)两种形式。在最大堆中,每个父节点的值都比其子节点的值大;在最小堆中,每个父节点的值都比其子节点的值小。

堆排序的基本步骤如下:

  1. 构建最大堆(或最小堆):将待排序的数组看作是一个完全二叉树的结构,并通过从最后一个非叶子节点开始,逐个向前调整节点的位置,使得每个父节点都大于(或小于)其子节点。
  2. 交换堆顶元素和最后一个元素:将堆顶元素(即最大值或最小值)与数组的最后一个元素进行交换。
  3. 调整堆:将剩余的 n-1 个元素重新构建成一个堆,再次找出最大(或最小)值,然后与当前堆的最后一个元素交换位置。
  4. 重复步骤 2 和步骤 3,直到排序完成。            建议不会的朋友可以去看看b站up主"请叫我AXing".

堆排序的实现

#include <stdio.h>// 交换两个元素的值
void swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}// 调整堆  i表示要维护的结点  n表示数组的长度
void heapify(int arr[], int n, int i) {int largest = i;  // 初始化最大元素为根节点int left = 2 * i + 1;  // 左子节点int right = 2 * i + 2;  // 右子节点// 如果左子节点比根节点大,则更新最大元素的索引if (left < n && arr[left] > arr[largest])largest = left;// 如果右子节点比当前最大元素大,则更新最大元素的索引if (right < n && arr[right] > arr[largest])largest = right;// 如果最大元素的索引不是根节点,交换根节点和最大元素if (largest != i) {swap(&arr[i], &arr[largest]);// 继续递归调整堆heapify(arr, n, largest);  //继续对堆的调整}
}// 堆排序函数
void heapSort(int arr[], int n) {// 构建最大堆(初始时假设数组已经是一个完全二叉树)for (int i = n / 2 - 1; i >= 0; i--)heapify(arr, n, i);// 重复交换堆顶元素和最后一个元素,并调整堆for (int i = n - 1; i > 0; i--) {swap(&arr[0], &arr[i]);heapify(arr, i, 0);}
}// 打印数组元素
void printArray(int arr[], int n) {for (int i = 0; i < n; i++)printf("%d ", arr[i]);printf("\n");
}// 测试示例
int main() {int arr[] = {12, 11, 13, 5, 6, 7};int n = sizeof(arr) / sizeof(arr[0]);printf("原始数组:\n");printArray(arr, n);heapSort(arr, n);printf("排序后的数组:\n");printArray(arr, n);return 0;
}

回到优先队列

在学会堆排序后,再看优先队列的代码,你会发现就是基本的队列加上了堆排序

代码实现

#include <stdio.h>
#include <stdlib.h>#define MAX_SIZE 100typedef struct {int priority;   //优先级int value;
} Element;typedef struct {Element elements[MAX_SIZE];int size;
} PriorityQueue;// 初始化优先队列
void initQueue(PriorityQueue* queue) {queue->size = 0;
}// 判断优先队列是否为空
int isEmpty(PriorityQueue* queue) {return (queue->size == 0);
}// 判断优先队列是否已满
int isFull(PriorityQueue* queue) {return (queue->size == MAX_SIZE);
}// 插入元素到优先队列
void enqueue(PriorityQueue* queue, int priority, int value) {if (isFull(queue)) { // 如果队列已满,则提示错误并返回printf("Priority Queue is full.\n");return;}Element newElement;newElement.priority = priority; // 赋值优先级newElement.value = value; // 赋值元素值// 将元素插入到队尾queue->elements[queue->size] = newElement;queue->size++;// 调整堆使得符合堆的性质int i = queue->size - 1; // 取新元素的下标while (i > 0 && queue->elements[i].priority < queue->elements[(i - 1) / 2].priority) {// 如果当前节点的优先级比父节点的优先级小,则交换当前节点和父节点的位置Element temp = queue->elements[i];queue->elements[i] = queue->elements[(i - 1) / 2];queue->elements[(i - 1) / 2] = temp;i = (i - 1) / 2; // 更新当前节点的下标 去到父结点}
}// 删除优先队列中具有最高优先级的元素
void dequeue(PriorityQueue* queue) {if (isEmpty(queue)) { // 如果队列为空,则提示错误并返回printf("Priority Queue is empty.\n");return;}// 将队尾元素移到队首queue->elements[0] = queue->elements[queue->size - 1];queue->size--;// 调整堆使得符合堆的性质int i = 0; // 从根节点开始调整while (1) {int leftChild = 2 * i + 1; // 左子节点的下标int rightChild = 2 * i + 2; // 右子节点的下标int smallest = i; // 最小值的下标,默认为当前节点的下标if (leftChild < queue->size && queue->elements[leftChild].priority < queue->elements[smallest].priority) {// 如果左子节点的优先级比当前节点的优先级小,则更新最小值的下标为左子节点的下标smallest = leftChild;}if (rightChild < queue->size && queue->elements[rightChild].priority < queue->elements[smallest].priority) {// 如果右子节点的优先级比当前节点的优先级小,则更新最小值的下标为右子节点的下标smallest = rightChild;}if (smallest != i) { // 如果最小值的下标不等于当前节点的下标,则交换当前节点和最小值的位置Element temp = queue->elements[i];queue->elements[i] = queue->elements[smallest];queue->elements[smallest] = temp;i = smallest; // 更新当前节点的下标}else { // 如果最小值的下标等于当前节点的下标,则调整完成,跳出循环break;}}
}int main() {PriorityQueue queue;initQueue(&queue); // 初始化队列// 插入测试数据enqueue(&queue, 2, 20);enqueue(&queue, 1, 10);enqueue(&queue, 3, 30);// 输出队首元素值printf("Front element: %d\n", queue.elements[0].value);// 删除队首元素dequeue(&queue);// 输出队首元素值printf("Front element: %d\n", queue.elements[0].value);return 0;
}

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

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

相关文章

Prometheus 教程

目录 一、简介二、下载安装1、安装 prometheus2、安装 alertmanager3、安装 grafana4、安装 node_exporter5、安装 mysqld_exporter 一、简介 Prometheus 是一个开源的系统监控和警报工具。它最初由 SoundCloud 开发&#xff0c;并于 2012 年发布为开源项目。Prometheus 专注于…

利用vite快速搭建vue3项目

1、选择一个文件夹&#xff0c;在vscode终端打开&#xff0c;输入命令【npm create vitelatest】 npm create vitelatest 2、提示你输入项目名称之后&#xff0c;我这里设置的是【rookiedemo】 3、回车之后&#xff0c;出现选择框架的提示&#xff0c;我们选择【vue】回车 4、…

js中使用for in注意事项,key的类型为string类型

for in是一个非常实用的存在&#xff0c;既可以遍历数组&#xff0c;又可以遍历对象&#xff0c;所以我一般都是会用来遍历可迭代的数据&#xff0c;遍历数组和对象的时候&#xff0c;要注意使用万能遍历方式&#xff1a; const users [1, 3, 45, 6]// const users {// 1…

Polyspace静态检测步骤

Polyspace 是一个代码静态分析和验证的工具&#xff0c;隶属于MATLAB&#xff0c;用于检测代码中的错误和缺陷&#xff0c;包括内存泄漏、数组越界、空指针引用等。帮助开发团队提高代码质量&#xff0c;减少软件开发过程中的错误和风险。 1、打开MATLAB R2018b 2、找到Polys…

AR智能眼镜主板硬件设计_AR眼镜光学方案

AR眼镜凭借其通过导航、游戏、聊天、翻译、音乐、电影和拍照等交互方式&#xff0c;将现实与虚拟进行无缝融合的特点&#xff0c;实现了更加沉浸式的体验。然而&#xff0c;要让AR眼镜真正成为便捷实用的智能设备&#xff0c;需要解决一系列技术难题&#xff0c;如显示、散热、…

Stable Diffusion 绘画入门教程(webui)-图生图

通过之前的文章相信大家对文生图已经不陌生了&#xff0c;那么图生图是干啥的呢&#xff1f; 简单理解就是根据我们给出的图片做为参考进行生成图片。 一、能干啥 这里举两个例子 1、二次元头像 真人转二次元&#xff0c;或者二次元转真人都行&#xff0c; 下图为真人转二次…

小清新卡通人物404错误页面源码

小清新卡通人物404错误页面源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 蓝奏云&#xff1a;https://wfr.lanzout.com/i6XbU1olftde

二叉树(6)——二叉树的创建和销毁

1 二叉树的创建 整体思路 将数组里的元素一直分为根&#xff0c;左子树&#xff0c;右子树&#xff0c;遇到#就返回NULL&#xff0c;链接到上层递归的左子树或者右子树&#xff0c;一定要把一个节点的左子树全部递归完才能返回到右子树。这种方法也可以scanf一个数组里的元素&…

Spring Boot项目怎么对System.setProperty(key, value)设置的属性进行读取加解密

一、前言 之前我写过一篇文章使用SM4国密加密算法对Spring Boot项目数据库连接信息以及yaml文件配置属性进行加密配置&#xff08;读取时自动解密&#xff09;&#xff0c;对Spring Boot项目的属性读取时进行加解密&#xff0c;但是没有说明对System.setProperty(key, value)设…

Docker Compose映射卷的作用是什么,dockerfile这个文件有什么区别和联系?

Docker Compose中映射卷&#xff08;Volumes&#xff09;的作用和Dockerfile之间既有区别也有联系。下面详细解释两者的作用、区别和联系&#xff1a; Docker Compose映射卷的作用 在Docker Compose中&#xff0c;卷&#xff08;Volumes&#xff09;用于数据持久化和数据共享…

【实战 JS逆向+python模拟获取+Redis token会话更新】实战模拟测试 某巴批发网 仅供学习

逆向日期&#xff1a;2024.02.20 使用工具&#xff1a;Node.js、python、Redis 加密方法&#xff1a;md5标准库 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理&#xff08;直接解密即可&#xff09;&#xff08;crypto-js.js 标…

day07-实战-今日指数

今日指数-day07 1.股票Code联想推荐 1.1 股票Code联想推荐功能介绍 1) 原型效果 输入框输入股票编码后&#xff0c;显示关联的股票信息; 2&#xff09;接口定义说明 接口说明&#xff1a; 功能描述&#xff1a;根据输入的个股代码&#xff0c;进行模糊查询&#xff0c;返…

Python学习-流程图、分支与循环(branch and loop)

十、流程图 1、流程图&#xff08;Flowchart&#xff09; 流程图是一种用于表示算法或代码流程的框图组合&#xff0c;它以不同类型的框框代表不同种类的程序步骤&#xff0c;每两个步骤之间以箭头连接起来。 好处&#xff1a; 1&#xff09;代码的指导文档 2&#xff09;有助…

云服务器ECS价格表出炉——阿里云

2024年阿里云服务器租用价格表更新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服…

docker (十一)-进阶篇-docker-compos最佳实践部署zabbix

一 部署docker环境 关闭防火墙、selinux、开启docker&#xff0c;并设置开机自启动 注意点&#xff1a;docker部署的时候&#xff0c;bip要指定&#xff0c;不然会导致虚拟机ip和容器ip冲突&#xff0c;ssh连不上虚拟机 部署请参考 docker &#xff08;二&#xff09;-yum…

【python】windowslinux系统python的安装

一、python官网及下载路径 官网地址&#xff1a;Welcome to Python.org 下载路径&#xff1a;Download Python | Python.org ​​​​​​​ linux源码安装包下载&#xff1a; windows二进制安装包下载&#xff1a; 二、Linux如何安装python 2.1 单版本安装 以安装python…

Codeforces Beta Round 15 C. Industrial Nim Nim,1~n的异或和

Problem - 15C - Codeforces 目录 Nim游戏&#xff1a; 1~n的异或和&#xff1a; 代码&#xff1a; Nim游戏&#xff1a; n个石头堆&#xff0c;谁最后没得取谁败 我用的异或思考法&#xff0c;对所有堆异或。开局异或和为0的败 最后全是0&#xff0c;异或完也是0. //最…

DDI中的自适应子结构

SA-DDI提出了一种子结构感知图神经网络&#xff0c;一种配备了子结构注意力机制和用于DDI预测的子结构-子结构交互模块&#xff08;SSIM&#xff09;的消息传递神经网络。具体而言&#xff0c;基于分子中官能团的尺寸和形状通常是不规则的化学直觉&#xff0c;子结构注意力被设…

线阵相机之帧超时

1 帧超时的效果 在帧超时时间内相机若未采集完一张图像所需的行数&#xff0c;则相机会直接完成这张图像的采集&#xff0c;并自动将缺失行数补黑出图&#xff0c;机制有以下几种选择&#xff1a; 1. 丢弃整张补黑的图像 2. 保留补黑部分出图 3.丢弃补黑部分出图

混子文章|蓝桥杯一题 -平方差

题目考点: 平方差 ,平方差奇偶关系 代码 #include<bits/stdc.h> #define Run 0 #define endl "\n" #define N 100005 using unl __int128_t; using ll long long; using namespace std; class Solution { public: void slove() {int sum 0;int L, R; cin &…