热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:.NET6优先队列PriorityQueue

篇首语:本文由编程笔记#小编为大家整理,主要介绍了.NET6优先队列PriorityQueue相关的知识,希望对你有一定的参考价值。在最近发布

篇首语:本文由编程笔记#小编为大家整理,主要介绍了.NET 6 优先队列 PriorityQueue相关的知识,希望对你有一定的参考价值。



在最近发布的 .NET 6 中,包含了一个新的数据结构,优先队列 PriorityQueue, 实际上这个数据结构在隔壁 Java中已经存在了很多年了, 那优先队列是怎么实现的呢

本文主要介绍了 .NET 6 新增的数据结构优先队列,感兴趣的也可以看一下 PriorityQueue 的源码, 其实就是基于堆这种结构实现的,也展示了入队和出队的堆结构的变化过程

另外需要注意的是,堆这种结构不是稳定的,因为在排序的过程,存在将堆的最后一个节点跟堆顶节点互换的操作

所以以相同优先级入队的元素并不能保证以相同的顺序出队。

 

时间复杂度

因为接下来会分析时间复杂度, 这里先贴一张几种时间复杂度的对比图,从低阶到高阶有:O(1)、O(logn)、O(n)、O(nlogn)、O(n2 )。

 

 什么是优先队列

首先,队列大家都知道, 是一个非常基础的数据结构, 它的特点是先进先出(FIFO)。

 

 而优先队列却不一定是先进先出,因为每个元素都有一个权重值, 代表着元素出队的优先级。

 

 队列可以用数组和链表实现, 简单、高效, 这样入队和出队的时间复杂度都是 O(1)。

 

优先队列能不能使用上面的方法呢?也可以, 但是每次新元素入队后, 需要和队列内的元素进行遍历和大小对比, 然后插入到合适的位置, 让整个序列保持从大到小或者从小到大,这样入队的时间复杂度变成 O(n), 而出队复杂度不变, 还是 O(1)。

O(n) 代表入队的时间是线性增长的, 效率较低, 有没有更高效的方法呢?

 
堆 Heap

堆这种数据结构的应用场景非常多,最经典的莫过于堆排序了, 堆排序是一种原地的、时间复杂度为 O(nlog n) 的排序算法,另外,堆也很适合用来做优先队列。

 

堆和树的结构其实是相似的, 堆有二叉堆, d-ary 堆, 2-3 堆, 斐波那契堆等等, 堆有一个特点就是每个父节点都大于等于它的儿子节点, 这种是大顶堆, 或者每个父节点都小于等于它的儿子节点, 这种是小顶堆,另外堆的儿子不分左右, 其中 java 中的 PriorityQueue 就是用二叉小顶堆实现的。

 

 

 

上面就是二叉堆, 而 .NET 6 中的 PriorityQueue 是由 d-ary 堆实现的, 而 d 表示父节点有几个儿子节点, .NET 6 中指定这个值为4,并且是小顶堆,也就是 “四叉小顶堆"。

 

 

 那么如何在代码中实现呢?其实可以用数组存储堆, 我们可以通过”广度优先遍历“ 的方法, 把堆的节点映射到一个数组中,如下

 

 

另外,堆和数组之间还有下面的关系

 

1.堆的顶点就是数组的第一个元素,也是最小的元素。
2.通过子节点的下标,就可以通过公式计算出父节点的下标, 公式为
P = (C - 1) / 4
其中 P = 父节点的下标, C = 子节点的下标

 

 现在优先队列的数据结构确定了, 接下来看元素的入队和出队。

入队 Enqueue

使用堆来实现优先队列,入队操作2步完成, 非常简单!

 

1.添加新节点到末尾
2.通过上面的公式 P = (C - 1) / 4, 新的子节点和父节点进行大小对比,如果子节点比较小,那么就和父节点交换,重复这个过程,直到子节点大于或等于父节点,或者子节点变成堆顶,堆化完成, 这个交换过程是从下往上的, 入队的时间复杂度是 O(log n)。

 

 

 出队 Dequeue

出队,就是每次取队列内最小的元素,基小顶堆结构,其实只需要取堆顶的元素即可,对应数组的第1个元素 array[0]。

你会发现,当取出堆顶元素以后,小顶堆的顶已经空了, 为了保持堆的结构,我们需要重新堆化。

和上面的入队 Enqueue 的逻辑有异曲同工之妙, 我们可以取堆的最后一个元素,把它放到堆顶, 然后父节点去和4个儿子节点比大小,如果比儿子节点大,就交换, 重复这个过程,直到父节点比4个儿子节点都大,

或者到达堆的最后一层,堆化完成,这个交换过程是从上往下的,出队的时间复杂度同样是 O(log n)。

另外,如果多个儿子节点都比父节点小,那父节点和最小的子节点交换。

 

 扩容和收缩机制

 

优先队列是用数组实现的四叉小顶堆, 那么就存在数组的扩容和收缩的情况

 

扩容:最小为4,数组满的时候会扩大为当前容量的2倍。

 

收缩:数组不会自动收缩,不过可以手动调用 TrimExcess() 方法, 当空余的空间大于10% 的时候, 数组的长度会收缩到当前队列元素的数量。

 


 



推荐阅读
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • http:www.cnblogs.comComputerGarchive201202012334898.html一:C语言中的内存机制在C语言中,内存 ... [详细]
  • 不懂性能优化,再强的计算机也白玩
    不懂性能优化,再强的计算机也白玩-Python的优秀有目共睹,不过说的性能,还真比不了Java、C、Go,有没有提升性能的技巧或方法呢?今天我们一起学习下提升Python性能的方式 ... [详细]
  • 简单数据结构模板
    一,STL1>STL中数据结构常见操作a.assign(b.begin(),b.begin()+3);b为向量,将b的0~2个元素构成的向量赋给aa.as ... [详细]
  • python自学教程哪里好,python比较好的教程
    本文目录一览:1、想学python去哪里比较好? ... [详细]
  • queue接口特点:可以模拟队列行为,即“先进先出”。接口结构queue接口继承了Collection接口,并增加了一些新方法12345678910111213141516publ ... [详细]
  • handler机制_Handler机制与原理
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Handler机制与原理相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Java回收对象的标记和对象的二次标记过程一、对象的标记1、什么是标记?怎么标记?第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收 ... [详细]
  • 【JVM技术专题】深入分析CG管理和原理查缺补漏「番外篇」
    前提概要本文主要针对HotspotVM中“CMSParNew”组合的一些使用场景进行总结。自Sun发布Java语言以来,开始使用GC技术来进行内存自动管理࿰ ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 1、tensorflow的基本运作为了快速的熟悉TensorFlow编程,下面从一段简单的代码开始:其中tf.mul(a,b)函数便是tf的一个基本的算数运算,接下来介绍跟 ... [详细]
  • 为什么需要有应用层缓冲区?muduo网络库使用IO复用,并且文件描述符使用非阻塞模式,如果使用阻塞模式那么read、write就会阻塞在 ... [详细]
  • 序本文主要研究一下nacosServiceManager的removeInstanceServiceManagernacos-1.1.3namingsrcmainjavacomal ... [详细]
  • LwIP系列内存管理(堆内存)详解
    一、目的小型嵌入式系统中的内存资源(SRAM)一般都比较有限,LwIP的运行平台一般都是资源受限的MCU。为了能够更加高效的运行ÿ ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
author-avatar
手机用户2502883723
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有