基于堆的优先队列及堆排序
来源:互联网 发布:服装销售软件 编辑:程序博客网 时间:2024/04/28 10:31
许多应用程序需要处理有序的元素,例如事件循环中要先处理高的事件。在这种情况下,我们设计的数据结构需要支持两种操作:删除最大元素和插入元素,这种数据类型就叫做优先队列,它可以用来解决TopM问题(找出M个最大的元素)或者多向归并问题(将多个有序的输出流合并成一个有序的输出流),在这两种情况下,问题的输入都可能是无限的,不可能先读取所有输入再进行排序,而优先队列适合解决这种问题。
先来看一下堆的概念,堆是二叉堆的简称,是一种每个节点的元素都大于两个子节点的完全二叉树,在优先队列中一般用数组表示。
优先队列的代码如下:
package chapter2;/** * Created by jia on 17-5-17. *///基于堆实现的优先队列public class MaxPQ<T extends Comparable<T>> { private T[] pq; //基于堆的完全二叉树 private int n; //数据存储于pq[1..n]中,pq[0]没有用到 public MaxPQ(int num) { pq = (T[]) new Comparable[num+1]; } public boolean isEmpty() { return n == 0; } public int size() { return n; } public void insert(T t) { pq[++n] = t; swim(n); } public T delMax() { T max = pq[1]; //根结点的元素值最大 swap(1, n--); //把最大值和最后一个元素交换,并将数组大小减一 pq[n+1] = null; //删除最大值 sink(1); //恢复堆的有序性 return max; } //递归地把节点i跟其父节点比较以构造二叉堆 private void swim(int i) { while (i > 1 && pq[i].compareTo(pq[i/2]) > 0) { swap(i, i/2); i /= 2; } } //递归地把节点i跟其两个子节点比较以构造二叉堆 private void sink(int i) { while (2*i <= n) { int j = 2*i; if (j < n && pq[j].compareTo(pq[j+1]) < 0) j++; if (pq[i].compareTo(pq[j]) >= 0) break; swap(i, j); i = j; } } private void swap(int i, int j) { T temp = pq[i]; pq[i] = pq[j]; pq[j] = temp; }}
堆排序的主要思想是构造一个最大元素的优先队列,然后再重复调用删除最大元素的方法来将它们按照顺序删除。堆排序分为两个阶段,先进行堆的构造,然后再用sink函数进行排序。代码如下:
package chapter2;/** * Created by jia on 17-5-17. */public class HeapSort { public static void sort(Comparable[] a) { //此时只能以a[0]为起点,为此要修改sink等函数 int n = a.length - 1; //先用for循环构造一个最大堆 for (int i = (n-1)/2; i >= 0; i--) { sink(a, i, n); } ArrayPrint.print(a); //再用sink函数进行排序 while (n > 0) { swap(a, 0, n); //每次循环都将当前的最大值放到a[n]处 sink(a, 0, --n); //再把n减去1,然后找出从0到n的最大值,放到a[0]处,下轮循环会把此值交换到a[n] } } private static void swap(Comparable[] a, int i, int j) { Comparable temp = a[i]; a[i] = a[j]; a[j] = temp; } private static void sink(Comparable[] a, int i, int n) { //n代表sink函数截止的最后一个数组索引值 while (2*i +1 <= n) { //以a[0]为起点的数组其元素a[i]的两个子节点是2*i+1和2*i+2 int j = 2*i + 1; if (j < n && a[j].compareTo(a[j+1]) < 0) j++; if (a[i].compareTo(a[j]) >= 0) break; swap(a, i, j); i = j; } } public static void main(String[] args) { String[] a = "21s1gwhfiajnc493tquwofadjst873ewigdshjk8y0qfwedsknlc49-ufqewojd;c2".split(""); sort(a); ArrayPrint.print(a); }}
阅读全文
4 1
- 基于堆的优先队列及堆排序
- 基于堆的优先队列和堆排序
- 基于二叉堆实现的优先队列和堆排序
- 堆排序 及 优先队列
- 最大堆及基于最大堆的最大优先队列
- 最小堆及基于最小堆的最小优先队列
- 基于堆的优先队列
- 基于堆的优先队列
- 基于堆的优先队列
- 基于堆的优先队列
- 堆的实现、堆排序、优先队列
- 数据结构与算法-堆、基于堆实现的优先队列、堆排序
- 堆、堆排序、优先队列
- 堆 优先队列 堆排序
- 用java实现一个基于堆排序的优先队列
- 堆和堆的应用:堆排序和优先队列
- 优先队列-堆排序
- 基于堆的优先队列的实现
- Spring Boot系列五 Spring @Value 属性注入使用总结二
- # Android 自定义View(二) 下雨效果
- 事务专题(二)
- 系统集成项目管理工程师学习笔记(五)项目整理管理
- 使用Hexo + Github搭建自己的私人博客
- 基于堆的优先队列及堆排序
- 流媒体直播防盗链安全控制
- Fiddler内置命令
- 自守数
- Longest Common Prefix
- 搭建samba服务器实现linux虚拟机与Windows宿主机文件共享
- Jupyter在mac上环境搭建 踩的坑,记录一下
- BZOJ 2306 [Ctsc2011] 幸福路径 [期望DP做法]
- offsetof和container_of总结