什么是heap
Heap 是一种数据结构,其中包含一个特殊的根节点,且每个节点的值都不小于(或不大于)其所有子节点的值。这种数据结构常用于实现优先队列。
Heap的数据结构
Heap 可以通过一个数组来实现,这个数组满足以下条件:
- 和二叉搜索树不同,堆并不需要满足左子节点小于父节点的值,右子节点大于父节点的值的条件。
- 堆中的一些列节点按照某种特定的顺序排列。这样的顺序可以是最小的元素在最前面,也可以是最大的元素在最前面。这个顺序满足父节点一定小于(或大于)它的所有子节点。
- 堆中的元素数量不一定是满的,也就是说堆并不一定是一个完全二叉树。
堆具有以下属性。
- 任何节点都小于(或大于)其所有后代,并且最小元素(或最大元素)位于堆的根(堆有序性)。
- 堆始终是一棵完整的树。即各级节点都填充除底层以外的元素,并且底层尽可能从左到右填充。
完全二叉树和满二叉树的区别如下所示。
根节点最大的堆称为最大堆或大根堆,根节点最小的堆称为最小堆或小根堆。
由于堆是完全二叉树,因此它们可以表示为顺序数组,如下所示。
如何实现优先级队列
优先队列是一种数据结构,其中每个元素都有一个优先级,优先级高的元素在前面,优先级相同时按照插入顺序排列。可以使用堆来实现优先队列。实现优先队列的关键是将一个元素添加到队列中,并保持队列中的元素有序。如果使用数组来存储元素,需要频繁对数组进行调整,时间复杂度是O(n),不够高效。如果使用堆来存储元素,则可以在插入时进行堆化,时间复杂度是O(nlogn)。
在堆中,节点的位置与它们在数组中的位置有一定的关系。例如,根节点位于数组的第一个元素,其他节点依次排列。左子节点位于(2i),右子节点位于(2i+1),父节点位于(i/2)。这个关系可以方便地实现在数组上进行堆化的操作。
为什么需要使用优先级队列
优先级队列是一种非常有用的数据结构,在很多应用中都会被广泛使用。比如作业调度、事件管理等领域,都需要使用优先级队列来帮助处理任务以及事件等的优先级顺序。
优点和缺点
优点
- 简单高效:优先级队列的实现较为简单,查找和插入等操作都可以在 O(log(n))O(log(n))O(log(n)) 的时间复杂度内完成,所以在实现简单的情况下,可以极大提高程序性能。
- 优先级:优先级队列可以根据任务或者事件的优先级,对其按照优先级大小进行排序,并在需要的时候依次处理。
缺点
- 空间占用:优先级队列需要占用额外的内存空间,以存储任务和事件的优先级信息。
- 任务时效性:当优先级较高的任务过多时,可能会导致低优先级任务的响应延迟,从而影响任务的时效性。
heap PriorityQueue实现
- 内部使用container/heap中的Interface接口实现堆结构;
- 提供了Push、Pop和PopByKey等一系列方法;
- 使用一个内部slice和一个以Key为索引的映射map来维护队列元素;
- 根据元素的Priority值进行优先级排序,Priority值越小表示优先级越高;
- 在Push时需要保证Key值唯一;
- PopByKey方法可以根据Key查找并移除对应的元素。
实现思路
既然,我们了解了heap的一些特性,那么我们接下来就要考虑如何用现有的数据结构,实现优先队列。
我们都知道,无论是哪一种队列,必然是存在生产者和消费者两个部分,对于优先级队列来说,更是如此。因此,咱们的实现思路,也将从这两个部分来谈。
生产者
对于生产者来说,他只需要推送一个任务及其优先级过来,咱们就得根据优先级处理他的任务。
由于,我们不大好判断,到底会有多少种不同的优先级传过来,也无法确定,每种优先级下有多少个任务要处理,所以,我们可以直接使用heap存储task
消费者
对于消费者来说,他需要获取优先级最高的任务进行消费。使用heap pop 取出优先级最高的任务即可
数据结构
(1)优先级队列对象
(2)任务对象
初始化优先级队列对象
在初始化对象时,需要先通过 NewPriorityQueue() 函数创建一个空的 PriorityQueue,然后再创建一个 PriorityQueueTask 对象,并将刚刚创建的 PriorityQueue 赋值给该对象的 pq 属性。同时,还要创建一个用于接收推送任务的管道,用于在生产者推送任务时,将新任务添加到队列中。
生产者推送任务
生产者向推送任务管道中推送新任务时,实际上是将一个 task 结构体实例发送到了管道中。在 task 结构体中,priority 属性表示这个任务的优先级,value 属性表示这个任务的值,key 属性表示这个任务的键。
消费者消费队列
消费者从队列中取出一个任务,然后进行相应的操作。在这段代码中,消费者轮询获取最高优先级的任务。如果没有获取到任务,则继续轮询;如果获取到了任务,则执行对应的操作。在这里,执行操作的具体形式是打印任务的编号、优先级等信息。