数据科学家成长之旅

关注 机器学习,深度学习,自然语言处理,数学

优先(级)队列

优先队列

  优先级队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序。每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储。
优先队列是由堆来实现的。
  重点:优先级队列,是要看优先级的,谁的优先级更高,谁就先得到权限。不分排队的顺序!如果优先队列中每个元素的优先级相同,则可任选其中一个。
  优先队列的效率:时间复杂度为O(logn),其中n为队列中元素的个数。
  

堆实质上是满足如下性质的完全二叉树:

  树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。

堆排序:

  堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

python中的优先队列

  Python的heapq模块实现了一个适用于Python列表的最小堆排序算法。是一个最小堆,堆顶元素 a永远是最小的,Java中的优先队列类似.

![优先级队列1](http://ogex32jwc.bkt.clouddn.com/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202016-12-27%2010.59.12.png)

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最小值,然后把该最小值所在的文件下一个数插入堆中,更新堆。

posted on 2017-03-03 17:37  会飞的蝸牛  阅读(313)  评论(0编辑  收藏  举报

导航