基于C#实现优先队列

一、堆结构

1.1性质

堆是一种很松散的序结构树,只保存了父节点和孩子节点的大小关系,并不规定左右孩子的大小,不像排序树那样严格,又因为堆是一种完全二叉树,设节点为 i,则 i/2 是 i 的父节点,2i 是 i 的左孩子,2i+1 是 i 的右孩子,所以在实现方式上可以采用轻量级的数组。
image.png

1.2用途

如果大家玩过微软的 MSMQ 的话,我们发现它其实也是一个优先队列,还有刚才说的抓取 url,不过很遗憾,为什么.net 类库中没有优先队列,而 java1.5 中就已经支持了。

1.3实现

<1> 堆结构节点定义:
我们在每个节点上定义一个level,表示该节点的优先级,也是构建堆时采取的依据。

 /// <summary>
 /// 定义一个数组来存放节点
 /// </summary>
 private List<HeapNode> nodeList = new List<HeapNode>();

 #region 堆节点定义
 /// <summary>
 /// 堆节点定义
 /// </summary>
 public class HeapNode
 {
     /// <summary>
     /// 实体数据
     /// </summary>
     public T t { get; set; }

     /// <summary>
     /// 优先级别 1-10个级别 (优先级别递增)
     /// </summary>
     public int level { get; set; }

     public HeapNode(T t, int level)
     {
         this.t = t;
         this.level = level;
     }

     public HeapNode() { }
 }
 #endregion

<2> 入队操作
入队操作时我们要注意几个问题:
①:完全二叉树的构建操作是“从上到下,从左到右”的形式,所以入队的节点是放在数组的最后,也就是树中叶子层的有序最右边空位。
②:当节点插入到最后时,有可能破坏了堆的性质,此时我们要进行“上滤操作”,当然时间复杂度为 O(lgN)。
image.png
当我将节点“20”插入到堆尾的时候,此时破坏了堆的性质,从图中我们可以清楚的看到节点“20”的整个上滤过程,有意思吧,还有一点就是:获取插入节点的父亲节点的算法是:parent=list.count/2-1。这也得益于完全二叉树的特性。

 #region  添加操作
 /// <summary>
 /// 添加操作
 /// </summary>
 public void Eequeue(T t, int level = 1)
 {
     //将当前节点追加到堆尾
     nodeList.Add(new HeapNode(t, level));

     //如果只有一个节点,则不需要进行筛操作
     if (nodeList.Count == 1)
         return;

     //获取最后一个非叶子节点
     int parent = nodeList.Count / 2 - 1;

     //堆调整
     UpHeapAdjust(nodeList, parent);
 }
 #endregion

 #region 对堆进行上滤操作,使得满足堆性质
 /// <summary>
 /// 对堆进行上滤操作,使得满足堆性质
 /// </summary>
 /// <param name="nodeList"></param>
 /// <param name="index">非叶子节点的之后指针(这里要注意:我们
 /// 的筛操作时针对非叶节点的)
 /// </param>
 public void UpHeapAdjust(List<HeapNode> nodeList, int parent)
 {
     while (parent >= 0)
     {
         //当前index节点的左孩子
         var left = 2 * parent + 1;

         //当前index节点的右孩子
         var right = left + 1;

         //parent子节点中最大的孩子节点,方便于parent进行比较
         //默认为left节点
         var max = left;

         //判断当前节点是否有右孩子
         if (right < nodeList.Count)
         {
             //判断parent要比较的最大子节点
             max = nodeList[left].level < nodeList[right].level ? right : left;
         }

         //如果parent节点小于它的某个子节点的话,此时筛操作
         if (nodeList[parent].level < nodeList[max].level)
         {
             //子节点和父节点进行交换操作
             var temp = nodeList[parent];
             nodeList[parent] = nodeList[max];
             nodeList[max] = temp;

             //继续进行更上一层的过滤
             parent = (int)Math.Ceiling(parent / 2d) - 1;
         }
         else
         {
             break;
         }
     }
 }
 #endregion

<3> 出队操作
从图中我们可以看出,优先级最大的节点会在一阵痉挛后上升到堆顶,出队操作时,我们采取的方案是:弹出堆顶元素,然后将叶子层中的最右子节点赋给堆顶,同样这时也会可能存在破坏堆的性质,最后我们要被迫进行下滤操作。
image.png
我图中可以看出:首先将堆顶 20 弹出,然后将 7 赋给堆顶,此时堆性质遭到破坏,最后我们清楚的看到节点 7 的下滤过程,从摊还分析的角度上来说,下滤的层数不超过 2-3 层,所以整体上来说出队的时间复杂度为一个常量 O(1)。

 #region 优先队列的出队操作
 /// <summary>
 /// 优先队列的出队操作
 /// </summary>
 /// <returns></returns>
 public HeapNode Dequeue()
 {
     if (nodeList.Count == 0)
         return null;

     //出队列操作,弹出数据头元素
     var pop = nodeList[0];

     //用尾元素填充头元素
     nodeList[0] = nodeList[nodeList.Count - 1];

     //删除尾节点
     nodeList.RemoveAt(nodeList.Count - 1);

     //然后从根节点下滤堆
     DownHeapAdjust(nodeList, 0);

     return pop;
 }
 #endregion

 #region  对堆进行下滤操作,使得满足堆性质
 /// <summary>
 /// 对堆进行下滤操作,使得满足堆性质
 /// </summary>
 /// <param name="nodeList"></param>
 /// <param name="index">非叶子节点的之后指针(这里要注意:我们
 /// 的筛操作时针对非叶节点的)
 /// </param>
 public void DownHeapAdjust(List<HeapNode> nodeList, int parent)
 {
     while (2 * parent + 1 < nodeList.Count)
     {
         //当前index节点的左孩子
         var left = 2 * parent + 1;

         //当前index节点的右孩子
         var right = left + 1;

         //parent子节点中最大的孩子节点,方便于parent进行比较
         //默认为left节点
         var max = left;

         //判断当前节点是否有右孩子
         if (right < nodeList.Count)
         {
             //判断parent要比较的最大子节点
             max = nodeList[left].level < nodeList[right].level ? right : left;
         }

         //如果parent节点小于它的某个子节点的话,此时筛操作
         if (nodeList[parent].level < nodeList[max].level)
         {
             //子节点和父节点进行交换操作
             var temp = nodeList[parent];
             nodeList[parent] = nodeList[max];
             nodeList[max] = temp;

             //继续进行更下一层的过滤
             parent = max;
         }
         else
         {
             break;
         }
     }
 }
 #endregion

image.png

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

张弛声音变现课,如何为偶像剧配音?

在为偶像剧进行配音工作时&#xff0c;配音员应当捕捉剧中角色的年轻活力、浪漫的爱情故事以及轻快的生活节奏。偶像剧主要讲述的是青春的爱恋、友谊和梦想追求&#xff0c;因此配音需要传递出剧中的真诚和活泼。为偶像剧配音可以考虑以下几点建议&#xff1a; 鲜明活泼的声音 …

2023亚太杯数学建模A题思路分析 - 采果机器人的图像识别技术

1 赛题 问题A 采果机器人的图像识别技术 中国是世界上最大的苹果生产国&#xff0c;年产量约为3500万吨。与此同时&#xff0c;中国也是世 界上最大的苹果出口国&#xff0c;全球每两个苹果中就有一个&#xff0c;全球超过六分之一的苹果出口 自中国。中国提出了一带一路倡议…

力控软件与多台PLC之间ModbusTCP/IP无线通信

Modbus TCP/IP 是对成熟的 Modbus 协议的改编&#xff0c; 因其开放性、简单性和广泛接受性而在工业自动化系统中发挥着举足轻重的作用。它作为连接各种工业设备的通用通信协议&#xff0c;包括可编程逻辑控制器 (PLC)、远程终端单元 (RTU) 和传感器。它提供标准化的 TCP 接口&…

租车系统开发/多功能租车平台微信小程序源码/汽车租赁系统源码/汽车租赁小程序系统

源码介绍&#xff1a; 多功能租车平台微信小程序源码&#xff0c;作为汽车租赁、摩托车租车平台系统源码&#xff0c;是小程序系统。基于微信小程序的汽车租赁系统源码。 开发环境及工具&#xff1a; 大等于jdk1.8&#xff0c;大于mysql5.5&#xff0c;idea&#xff08;eclip…

GIT,解决远程分支冲突

背景&#xff1a;当远程分支A 与maste 有冲突如何解决–此时无法在这两个版本之间merge 1、切换到master分支&#xff1a; git checkout master 2、更新master分支代码&#xff1a; git pull 3、再次切换到自己新建的分支&#xff1a; git checkout add_login_check_func 4、将…

matlab使用scatter函数画图时报错“数组索引必须为正整数或逻辑值”解决办法

一、背景 在使用matlab的scatter函数画图时报错“数组索引必须为正整数或逻辑值”。 scatter函数说明&#xff1a;scatter(x,y) 在向量 x 和 y 指定的位置创建一个包含圆形标记的散点图。 二、解决办法 如果使用scatter函数时报上述错误&#xff0c;尝试将连续函数先转换为函…

Git使用基础总结(从小白到新手版)

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…

双系统Ubuntu-22.04.3安装编译kaldi

Ubuntu物理内存要求85-100G以上&#xff0c;运行内存5-6G以上&#xff08;如果第一次安装的Ubuntu物理内存不够&#xff0c;请勿进行扩容&#xff0c;扩容易出现黑屏、蓝屏、死机的情况&#xff0c;应该卸载Ubuntu重新安装&#xff0c;在安装过程中进行内存分配&#xff1b;运行…

德迅云安全-德迅卫士:保障您的主机安全

主机安全是指保证主机在数据存储和处理的保密性、完整性、可用性&#xff0c;包括硬件、固件、系统软件的自身安全&#xff0c;以及一系列附加的安全技术和安全管理措施。 为什么要主机安全&#xff1f; 服务器一旦被黑客入侵&#xff0c;个人和企业面临以下安全风险&#xff…

Navicat 技术指引 | 适用于 GaussDB 的模型功能

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

【AI读论文】AutoML的8年回顾:分类、综述与趋势

论文标题&#xff1a;Eight years of AutoML: categorisation, review and trends 论文链接&#xff1a;https://link.springer.com/article/10.1007/s10115-023-01935-1 本文主要围绕自动机器学习&#xff08;AutoML&#xff09;展开了系统性的文献综述&#xff0c;总结了该领…

CVE-2022-21661

简介 CVE-2022-21661是一个与WordPress相关的漏洞&#xff0c;涉及到SQL注入问题。该漏洞主要源于WordPress的WQ_Tax_Query类中的clean_query函数&#xff0c;可能允许攻击者通过控制传递给该函数的数据来控制生成的SQL查询&#xff0c;从而执行任意的SQL代码。 当WordPress的…

openEuler 22.03 LTS x86_64 cephadm 部署ceph18.2.0 未完成 笔记

环境 准备三台虚拟机 10.47.76.94 node-1 10.47.76.95 node-2 10.47.76.96 node-3 下载cephadm [rootnode-1 ~]# yum install cephadm Last metadata expiration check: 0:11:31 ago on Tue 21 Nov 2023 10:00:20 AM CST. Dependencies resolved. Package …

学生护眼台灯哪个牌子最好?考研必备五款护眼台灯推荐

2023年6月6日&#xff0c;第28个全国“爱眼日”。国家卫健委发布数据显示&#xff0c;2022年全国儿童青少年总体近视率为53.6%&#xff0c;超过一半&#xff1b;其中6岁儿童为14.5%&#xff0c;小学生为36%&#xff0c;初中生为71.6%&#xff0c;高中生为81%。 学生护眼台灯哪个…

测绘资质技术管理制度

技术管理制度 建立健全技术管理制度&#xff0c;明确技术设计、技术处理和技术总结等要求。其中简单、日常性的测绘项目可以制定《作业指导书》 质量检查管理制度 建立健全质量检查管理制度&#xff0c;明确过程检查、最终检查、质量评定、检查记录和检查报告等要求。 人员培训…

玻璃加工ERP包含些模块?玻璃加工ERP好用吗

玻璃制品的类型多、规格不一、营销策略灵活、销售渠道广泛、生产关联业务环节。在当今这个市场竞争日益激烈的时代&#xff0c;如何有效整合各个业务环节&#xff0c;提升多部门协作效率&#xff0c;随时进行数据分析等&#xff0c;是每个玻璃加工企业面临的管理难题。 在数字…

4.18每日一题(极坐标累次积分到直角坐标累次积分的转换)

注&#xff1a;rdr化为直角坐标以后r直接消去了&#xff0c;不需要计算

购买Zoho CRM系统要花多少钱?

相信对CRM系统有过了解的人都知道&#xff0c;CRM系统的价格取决于功能需求&#xff0c;用户数量&#xff0c;部署方式&#xff0c;定制开发等因素。Zoho CRM是全球领先的云CRM系统&#xff0c;自2005年推出以来&#xff0c;累计服务25万企业&#xff0c;那么Zoho CRM系统的价格…

【ROS 2 进阶-MoveIt!】MoveIt!中的关键节点

所有内容请查看&#xff1a;博客学习目录_Howe_xixi的博客-CSDN博客 原文档链接&#xff1a;Docs