`
风子柒
  • 浏览: 55198 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

要去哪里找 像你这么好 ——从堆到优先队列的实现

阅读更多
     优先队列,顾名思义,就是一种根据一定优先级存储和取出数据的队列。它可以说是队列和排序的完美结合体,不仅可以存储数据,还可以将这些数据按照我们设定的规则进行排序。

     先说说优先队列的实现吧。有一点需要澄清,很多人一直以为Priority Queue就是一个Priority Heap,这种说法当然是片面的。既然优先队列只是存储数据和排序的结合,那么根据我们学过的知识,可以列出以下的实现方法:无序数组、无序链表、有序数组、有序链表以及二叉查找树,当然还有堆。这些方法在实现中当然也有优先级,下表就是一些方法的实现基本操作的时间性能对比:



图1.一些优先队列的实现方案的时间性能对比


     从这张表里我们可以按照时间复杂度这个优先级来进行一次排序,当然,你会选用最后一种二叉查找树作为实现优先队列的方案,但是实际上我们采用的是堆。堆,就是一种二叉树,堆和二叉查找树是类似的,但是也有些许不同:从形状来看,二叉查找树可以有不同的形状,而堆只能是完全二叉树;在时间性能上,二者并无明显的区别。堆也是有序的,我们一般将其分为大顶堆和小顶堆。小顶堆,顾名思义,就是这个堆的子结点的值小于父结点的值;相反的,大顶堆就是堆的子结点的值都大于父结点的值。
     在实现的时候,我们常常使用基于数组的堆,即堆中的元素保存在一个数组中,而这个数组元素的保存也是按照一定规律的:如果父结点的位置为n,那么,其对应的左右子结点的位置分别是2n+1和2n+2。也就是说,我们在视觉上(如果用画图形象化表示堆的话)和本质上将堆打扮成两种东西,这样既便于理解,也利于实现,本质的实现是用数组是因为考虑到数组的一些性能。
     堆有两个很基本的操作:增加、删除。先来说说增加元素,假设有下面这样一个堆:



     这时候,有一个元素1要添加进来,这时候应该怎么办呢?第一步,将元素添加到堆的最后一个位置:



     第二步,将新加入的元素与其父结点的值进行比较,若新结点的值比其父结点的值要小(就像这个例子一样),那么,交换两个结点的值,重复第二步,直到形成一个小顶堆:






     这样,一个新的小顶堆诞生了!
     然后就是从堆中删除一个元素了,假设在这个新的小顶堆中,我们打算删除堆顶元素:
     第一步,将这个1删掉,假设其结点上当前没有值:





     第二步,将最后一个结点的值放在根的位置,然后进行下滤,比较一下两个子结点的值与根节点的值,将堆顶元素与其子结点中较小的交换,然后重复:










     知道了这些基本的原理,对数据量更大的增加和删除也应该是触类旁通了吧。
     有人会质疑堆中除堆顶元素之外的其他元素的顺序问题:



     比如这里为什么4会放在5的右边兄弟结点上,这明显是受了二叉查找树的影响,因为堆对我们来说,一般只有堆顶元素有用,因此只要保证堆顶元素是最小的就行了(对小顶堆)。

     下面,简单介绍一下sun提供的PriorityQueue的一些基本的方法,以此来较为深入地理解优先队列的实现机制:
     1.下面是PriorityQueue的声明的第一句话:



     这句话表明:sun提供的优先队列是基于优先堆实现的;
     2.下面是声明一个Object数组时的注释:



     由此可知,堆中的元素在数组中的保存方案;并且队列中的优先级最小的元素总是保存在queue[0]中,前提是该优先队列不为空。
     下面是往PriorityQueue中上滤的方法:



     这段代码中,k代表当前加入元素的位置,即最后一个位置+1,x表示要添加的元素。首先得到父结点的值,然后将x的值和父结点的值进行比较,如果子结点的值大于父结点值,不作更改,否则交换两者的值。这个方法主要用于添加元素的时候。与之相对应的有一个下滤方法siftDownComparable(),其功能是向下比较,用在删除元素的实现中;
      接下来就讲添加元素的实现:



     这里可以看到用到了siftUp方法,其实,siftUp中分情况调用了 siftUpUsingComparator()、siftUpComparable()。这在刚才已经介绍了上滤的实现了。这里的添加元素就是上滤的过程。
     当然,我们在使用时,一般使用的方法是这三种:add、poll以及peek,add用以添加元素,其内部是用offer方法实现的,peek用来得到堆顶元素,但是不删除,而poll在返回堆顶元素之后,将堆顶元素删除。

     以上只是对优先队列的简要介绍,作为一个应用比较广泛的数据结构,优先队列还有许许多多奇妙的地方,它们都等着你去发现。

  • 大小: 19.3 KB
  • 大小: 5.1 KB
  • 大小: 5.8 KB
  • 大小: 5.4 KB
  • 大小: 5.6 KB
  • 大小: 5.8 KB
  • 大小: 5.7 KB
  • 大小: 5.8 KB
  • 大小: 5.4 KB
  • 大小: 5.4 KB
  • 大小: 9.3 KB
  • 大小: 15.7 KB
  • 大小: 17.4 KB
  • 大小: 16.4 KB
  • 大小: 8.3 KB
  • 大小: 7.3 KB
  • 大小: 7.4 KB
5
1
分享到:
评论

相关推荐

    lazy_binomial_heap的python实现——lazy 二项堆——优先队列。

    lazy binomial heaps的oython实现,优先队列。采用双向循环链表实现,api:merge,insert,find_min,extractMin,coalesce_step,updateMin。

    数据结构课设——小大根交替堆实现的双端优先级队列及应用

    数据结构课设——小大根交替堆实现的双端优先级队列及应用

    数据结构——堆.pdf

    数据结构——堆 1.容易蒙圈的概念问题 ⼀般我在学习⼀个新的东西的时候都会在脑⼦⾥有⼀⼤堆问题!那么到底堆是什么?是⼀种什么样的数据结构呢?⽤堆可以来⼲什么呢? 让我来⾃问⾃答哈:堆其实说⽩了就是⼀种这类...

    《数据结构》——队列的操作

    用C++实现的。顺序存储和链式存储都封装成了类。里面的注释写了些提示,希望能有所帮助。

    Python中的堆实现:heapq 模块——利用堆结构实现快速访问数据流中的中位数

    堆结构是一种优先队列,可以以任意顺序添加对象,并随时查找或删除最小(大)的元素,或者查找和删除前 K 个最小(大)元素。相比于列表方法min() / max(),这样做的效率要高得多。 堆结构是一种特殊的完全二叉树...

    通俗易懂的啊哈C语言1

    第3节 堆——神奇的优先队列 185 第4节 擒贼先擒王——并查集 200 第8章 更多精彩算法 211 第1节 镖局运镖——图的zui小生成树 212 第2节 再谈zui小生成树 219 第3节 重要城市——图的割点 229 第4节 关键...

    数据结构与算法分析Java语言描述(第二版)

    堆6.6 左式堆6.6.1 左式堆性质6.6.2 左式堆操作6.7 斜堆6.8 二项队列6.8.1 二项队列结构6.8.2 二项队列操作6.8.3 二项队列的实现6.9 标准库中的优先队列小结练习参考文献第7章 排序7.1 预备知识7.2 插入排序7.2.1...

    数据结构与算法分析C描述第三版

    第6章 优先队列(堆)   6.1 模型   6.2 一些简单的实现   6.3 二叉堆   6.3.1 结构性质   6.3.2 堆序性质   6.3.3 基本的堆操作   6.3.4 堆的其他操作   6.4 优先队列的应用   6.4.1 ...

    数据结构与算法分析-Java语言描述(第2版)_2_2

    小结 练习 参考文献第6章 优先队列(堆) 6.1 模型 6.2 一些简单的实现 6.3 二叉堆 6.3.1 结构性质 6.3.2 堆序性质 6.3.3 基本的堆操作 6.3.4 其他的堆操作 6.4 优先队列的应用 6.4.1 选择问题...

    数据结构与算法分析-Java语言描述(第2版)_1_2

    小结 练习 参考文献第6章 优先队列(堆) 6.1 模型 6.2 一些简单的实现 6.3 二叉堆 6.3.1 结构性质 6.3.2 堆序性质 6.3.3 基本的堆操作 6.3.4 其他的堆操作 6.4 优先队列的应用 6.4.1 选择问题...

    数据结构与算法分析第二版 ---C语言描述(附加答案)

    散列5.1 一般想法5.2 散列函数5.3 分离链接法5.4 开放定址法5.4.1 线性探测法5.4.2 平方探测法5.4.3 双散列5.5 再散列5.6 可扩散列总结练习参考文献第6章 优先队列(堆)6.1 模型6.2 一些简单的实现6.3 二叉堆6.3.1 ...

    数据结构与算法分析

    书的内容包括表、栈、队列、树、散列表、优先队列、排序、不相交集算法、图论算法、算法分析、算法设计、摊还分析、查找树算法、k-d树和配对堆等。本书适合作为计算机相关专业本科生的数据结构课程和研究生算法分析...

    数据结构与算法分析_Java语言描述(第2版)]

    堆6.6 左式堆6.6.1 左式堆性质6.6.2 左式堆操作6.7 斜堆6.8 二项队列6.8.1 二项队列结构6.8.2 二项队列操作6.8.3 二项队列的实现6.9 标准库中的优先队列小结练习参考文献第7章 排序7.1 预备知识7.2 插入排序7.2.1 ...

    数据结构与算法分析 Java语言描述第2版

    堆6.6 左式堆6.6.1 左式堆性质6.6.2 左式堆操作6.7 斜堆6.8 二项队列6.8.1 二项队列结构6.8.2 二项队列操作6.8.3 二项队列的实现6.9 标准库中的优先队列小结练习参考文献第7章 排序7.1 预备知识7.2 插入排序7.2.1 ...

    数据结构与算法分析_Java语言描述(第2版)

    第6章 优先队列(堆) 6.1 模型 6.2 一些简单的实现 6.3 二叉堆 6.3.1 结构性质 6.3.2 堆序性质 6.3.3 基本的堆操作 6.3.4 其他的堆操作 6.4 优先队列的应用 6.4.1 选择问题 6.4.2 事件模拟 6.5 d-堆 6.6 左式堆 ...

    算法:算法C语言实现 第1-4部分 基础知识、数据结构、排序及搜索

    第三部分“排序”(第6~11章)按章节顺序分别讨论基本排序方法(如选择排序、插入排序、冒泡排序、希尔排序等)、快速排序方法、归并和归并排序方法、优先队列与堆排序方法、基数排序方法以及特殊用途的排序方法,...

    严蔚敏 数据结构(C语言版) 代码 23490 书中算法

    3.4.2 循环队列——队列的顺序表示和实现 62 3.4.3 链队——队列的链式表示和实现 65 3.5 队列的应用 67 3.6 小结 69 习题 69 第4章 串、数组和广义表 73 4.1 串 73 4.1.1 串的类型定义 73 4.1.2 串...

    《算法精解:C语言描述》(Kyle Loudon[美] 著,肖翔、陈舸 译)

    本书中的代码尤为值得强调:所有实现都采用C语言编写,所有代码都优先用于教学目的,所有代码都在4种平台上经过完整测试,头文件记录了所有公共的接口,命名规则适用于全书所有的代码,所有的代码都包含大量注释……...

Global site tag (gtag.js) - Google Analytics