LeetCode基础-排序-二叉堆排序(优先队列)
来源:互联网 发布:php会员中心 源码 编辑:程序博客网 时间:2024/05/18 15:51
有些情况下要求不一定要求数组全部有序,或者说不一定要一定性全部有序。
有些情况下先收集一些元素,找到这些元素中的最大值,然后重复这个步骤。
比如,电脑或手机上运行的多个应用程序,可以给每个程序分配一个优先队列,并总是处理下一个优先级最高的那个应用程序。
这就需要优先队列了,它支持这两种操作:
- 删除最大元素
- 插入元素
优先队列与队列(删除最老元素)和栈(删除最新元素)类似,但更高效。
二叉堆数据结构能够很好的实现优先队列的两种操作。二叉堆就像是一个完全二叉树。
有序的堆能够保证父结点大于两个子结点,根结点是最大结点。
位置 k 的结点的父结点的位置是 k/2,而他的子结点的位置是 2k 和 2k+1。
我们用长度为 N+1 的数据 pq[] 来表示一个大小为 N 的堆,不使用 pq[0](为了方便计算),所有堆元素放在 pq[1] 至 pq[N] 中。
首先将二叉堆排序:
- 从下至上的有序化(上浮)swim()
- 从上至下的有序化(下沉)sink()
如果堆的有序状态因为某个结点变得比它的父结点更大,那么就需要交换二者的顺序,以重新恢复堆的规则,直至小于其父结点。
public void swim(int k){ while(k > 1 && k/2 < k) { exchange(k/2, k); k = k/2; }}
如果堆的有序状态因为某个结点变得比它的两个子结点或是其中之一更小,那么就需要与两个子结点的较大者交换顺序,以重新恢复堆的规则,直至大于其子结点。
public void sink(int k){ while(2*k < = N) { int j = 2*k; if(j < N && j < j+1) { j++; } if(k >= j) { break; } exchange(k, j); k = j; }}
当插入元素时,我们将新元素加至数组末尾,改变堆的大小,然后让这个元素 swim 到合适的位置。
此操作的比较次数不超过 lgN+1。
当删除最大元素时,我们从数组顶端删去最大元素,改变堆的大小,并将数组的最后一个元素放至顶端,然后让这个元素 sink 至合适的位置。
此操作的比较次数不超过 2 * lgN。
任意优先队列可以变成堆排序。堆排序可以分为两个阶段:
- 将数组构造成堆:从右至左用 sink() 函数构造子堆。
- 下沉排序,从堆中按递减顺序取出所有元素并排序。
public void sort(int[] a){ int N = a.Length; for(int k = N/2; k >= 1; k--) { sink(a[k]); } while(N > 1) { exchange(a[1], a[N--]); sink(a[1]); } }
上面的代码将 a[1] 到 a[N] 的元素进行排序,for 循环构造堆。while 循环把 a[1] 和 a[N] 交换并修复堆,直到堆变空。
常见题型:
- 从10亿个元素中找出最大的10个。
- LeetCode基础-排序-二叉堆排序(优先队列)
- 优先队列(二叉堆实现) + 堆排序
- 算法基础:排序(四)——二叉堆、优先队列、堆排序——Python实现
- 堆排序(优先队列)
- 堆排序(优先队列)
- 优先队列-堆排序
- 完全二叉树,堆,堆排序,优先队列
- 基于二叉堆实现的优先队列和堆排序
- 堆、堆排序、优先队列
- 堆 优先队列 堆排序
- 优先队列 之 堆排序实现(堆排序思想)
- 优先队列之堆排序(一)
- 堆排序和 优先队列
- 堆排序与优先队列
- 堆排序和优先队列
- 堆排序,优先队列实现
- 堆排序以及优先队列
- 优先队列和堆排序
- Angular4-在线竞拍应用-组件的生命周期
- 【视频集】iPhone X 开箱+评测视频汇总(主流媒体)
- JDK的安装和Android SDK的升级和讲解
- 20171026-每日一练
- Docker删除none镜像
- LeetCode基础-排序-二叉堆排序(优先队列)
- JavaBean中Integer类型为null时,转为json依然为null
- NOIP模拟(20171030)T2 游戏
- 2017 Web 开发安全问题 TOP10,看看中枪了没?
- C语言指针细节_1
- C#数组赋值
- 前端面试题(5) 列举5种IE haslayout的属性及其值
- C#模拟http 发送post或get请求
- [NOIP模拟]BZOJ 2143 飞飞侠