基于堆的优先队列及堆排序
2017-05-17 22:38
190 查看
许多应用程序需要处理有序的元素,例如事件循环中要先处理高的事件。在这种情况下,我们设计的数据结构需要支持两种操作:删除最大元素和插入元素,这种数据类型就叫做优先队列,它可以用来解决TopM问题(找出M个最大的元素)或者多向归并问题(将多个有序的输出流合并成一个有序的输出流),在这两种情况下,问题的输入都可能是无限的,不可能先读取所有输入再进行排序,而优先队列适合解决这种问题。
先来看一下堆的概念,堆是二叉堆的简称,是一种每个节点的元素都大于两个子节点的完全二叉树,在优先队列中一般用数组表示。
优先队列的代码如下:
堆排序的主要思想是构造一个最大元素的优先队列,然后再重复调用删除最大元素的方法来将它们按照顺序删除。堆排序分为两个阶段,先进行堆的构造,然后再用sink函数进行排序。代码如下:
先来看一下堆的概念,堆是二叉堆的简称,是一种每个节点的元素都大于两个子节点的完全二叉树,在优先队列中一般用数组表示。
优先队列的代码如下:
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 处 sink(a, 0, --n); //再把n减去1,然后找出从0到n的最大值,放到a[0]处,下轮循环会把此值交换到a } } 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); } }
相关文章推荐
- 基于二叉堆实现的优先队列和堆排序
- 用java实现一个基于堆排序的优先队列
- 基于二叉树的堆排序、优先队列、二叉查找树、平衡查找树、B树详解
- 算法设计之,堆,堆排序,基于最大堆的最大优先队列的实现(C++实现)
- 堆、堆排序和优先队列的那些事
- Java基于堆结构实现优先队列功能示例
- 排序算法——优先队列(基于堆得优先队列)
- 算法基础:排序(四)——二叉堆、优先队列、堆排序——Python实现
- Python 使用list实现无边际优先队列 (基于class, 包含迭代器)
- 算法基础:排序(四)——二叉堆、优先队列、堆排序——Python实现
- 数据结构与算法--优先队列和堆排序
- 最大堆及基于最大堆的最大优先队列
- 排序算法之——优先队列经典实现(基于二叉堆)
- 基于算法导论6.5用最大堆实现的优先队列(C++)
- 利用优先队列实现堆排序(自顶向下自底向上堆化完全二叉树的运用)
- HDU1285基于有向图邻接表的优先队列的拓扑排序
- 优先队列 之 堆排序实现(堆排序思想)
- 基于event 实现的线程安全的优先队列(python实现)
- 算法 2.4节 堆排序及其改进、索引优先队列
- 优先队列与堆排序