优先队列
Posted ppwq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优先队列相关的知识,希望对你有一定的参考价值。
支持两种操作:删除最大元素和插入元素的数据类型叫做优先队列。
队列:删除最老的元素。
栈:删除最新的元素。
基于二叉堆数据结构的一种优先队列的经典实现方法,用数组保存元素并按照一定条件排序。
数据结构二叉堆能够很好地实现优先队列的基本操作。在二叉堆的数组中,每个元素都要保证大于等于另两个特定位置的元素。相应地,这些位置的元素又至少要大于等于数组中的另两个元素。
当一个二叉树的每个结点都大于等于它的两个子结点时,它被称为堆有序。根节点是堆有序的二叉树中的最大结点。
二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组中按照层级储存(不适用数组的第一个位置)。
基于堆的优先队列
public class MaxPQ<Key extends Comparable<Key>> { private Key[] pq; //基于堆的完全二叉树 private int N = 0; //存储于pq[1..N]中,pq[0]没有使用 public MaxPQ(int maxN) { pq = (Key[]) new Comparable[maxN+1]; } public boolean isEmpty() { return N == 0; } public int size() { return N; } public void insert(Key v) { pq[++N] = v; swim(N); } public Key delMax() { Key max = pq[1]; //从根节点得到最大元素 exch(1, N--); //将其和最后一个结点交换 pq[N+1] = null; //防止越界 sink(1); //恢复堆的有序性 return max; } private boolean less(int i, int j) { return pq[i].compareTo(pq[j]) < 0; } private void exch(int i, int j) { Key t = pq[i]; pq[i] = pq[j]; pq[j] = t; } private void swim(int k) { //由下至上的堆有序化(上浮)的实现 while (k >1 && less(k/2, k)) { exch(k/2, k); k = k/2; } } private void sink(int k) { //由上至下的堆有序化(下沉)的实现 while (2*k <= N) { int j = 2*k; if (j < N && less(j, j+1)) j++; if (!less(k, j)) break; exch(k, j); k = j; } } }
优先队列由一个基于堆的完全二叉树表示,存储于数组pq[1..N]中,pq[0]不使用。若含有N个元素,则插入元素操作只需不超过(lgN+1)次比较,删除最大元素操作需要不超过2lgN次比较。
堆排序
堆排序分为两个阶段。在堆的构造阶段,将原始数据重新组织进一个堆中;然后在下沉排序阶段,我们从堆中按递减顺序取出所有元素并得到排序结果。
public static void sort(Comparable[] a) { int N = a.length; for (int k = N/2; k >= 1; k--) sink(a, k, N); while (N > 1) { exch(a, 1, N--); sink(a, 1, N); } }
用sink()方法首先将数组里的元素排序,for循环构造了堆,然后while循环将最大的元素a[1]和a[N]交换,N值减一并修复新堆,如此重复直到堆变空。
以上是关于优先队列的主要内容,如果未能解决你的问题,请参考以下文章