优先(级)队列
优先队列
优先级队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序。每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储。
优先队列是由堆来实现的。
重点:优先级队列,是要看优先级的,谁的优先级更高,谁就先得到权限。不分排队的顺序!如果优先队列中每个元素的优先级相同,则可任选其中一个。
优先队列的效率:时间复杂度为O(logn),其中n为队列中元素的个数。
堆实质上是满足如下性质的完全二叉树:
树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
堆排序:
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
python中的优先队列
Python的heapq模块实现了一个适用于Python列表的最小堆排序算法。是一个最小堆,堆顶元素 a永远是最小的,Java中的优先队列类似.
heapq模块提供了如下几个函数:
- heapq.heappush(heap, item) :把item添加到heap中(heap是一个列表)
- heapq.heappop(heap) : 把堆顶元素弹出,返回的就是堆顶(优先级最高的元素)
- heapq.heappushpop(heap, item) :先把item加入到堆中,然后再pop,比heappush()再heappop()要快得多
- heapq.heapreplace(heap, item) :先pop,然后再把item加入到堆中,比heappop()再heappush()要快得多
- heapq.heapify(x) :将列表x进行堆调整,默认返回的是小顶堆
- heapq.merge(*iterables) :将多个列表合并,并进行堆调整,返回的是合并后的列表的迭代器
- heapq.nlargest(n, iterable, key=None) 返回最大的n个元素(Top-K问题)
- heapq.nsmallest(n, iterable, key=None) 返回最小的n个元素(Top-K问题)
其他具体信息可见详细官方文档。
优先级队列的应用:
堆排序
可以用优先级队列,堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
哈夫曼编码
哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
大型浮点数集合的和
由于比较小的浮点数和比较大的浮点数相加会损失比较大的精度,所以要在集合中找出两个比较小的浮点数进行相加。类似哈弗曼编码。
将很多较小的有序文件归并为一个较大的文件
从多个有序文件中选择一个最小的数,正常的简单做法是扫描多个有序小文件,记录最小值。假设有n个有序小文件,那么时间复杂度就是O(n)。这里可以用优先级队列来选择一个最小的数,时间复杂度为O(nlogn)。 具体做法是建立n元堆,extract最小值,然后把该最小值所在的文件下一个数插入堆中,更新堆。