1. 优先队列
优先队列支持的两种操作:删除最大(小)元素,插入元素。和队列以及栈类似。
可以将优先队列比作一个黑盒:里面存放最大(小)的若干元素,支持向里面添加元素,取出删除最大(小)元素。
jdk自带实现:PriorityQueue.
jdk还有双向顺序队列ArrayDeque和双向链式队列LinkedList。
实现方法:
1).数组无序实现:insert()方法和栈的push()方法一样,删除最大元素可以内循环找出最大元素然后和边界元素交换删除。
2).数组有序实现:插入时保持数组有序,删除时直接删除边界元素。
3).链表实现。
4).堆实现。
比较:
| 数据结构 | 插入元素 | 删除元素 |
| 有序数组 | N | 1 |
| 无序数组 | 1 | N |
| 堆 | logN | logN |
| 理想情况 | 1 | 1 |
2.堆
用完全二叉树来表示堆,用数组即可实现。为方便表示不使用数组第一个位置,根节点在位置1,设一节点在位置k,则它的子节点在2k和2k+1,父节点在k/2。
堆里面最重要的操作就是要保证堆有序的两个操作:上浮swim()和下沉sink()。上浮是以此节点开始,比较它和父节点的值,若不满足堆,则交换位置,直到根节点。下沉类似:和其子节点比较,不满足堆则交换,直到到达堆的底部。
插入操作:将新元素放到数组末尾,增加堆的大小并上浮新元素到合适位置。
删除最大(小)元素:从数组顶端删除最大(小)元素,并将数组最后一个元素放到顶端,减小堆大小,下沉该元素到合适位置。
用堆实现的优先队列:
1 //优先队列,用堆实现 2 //可以向队列插入数据,并删除最大的数,插入删除的的复杂度都是logN 3 public class MaxPQ <Key extends Comparable<Key>>{ 4 private Key[] pq; 5 private int N = 0; 6 7 @SuppressWarnings("unchecked") 8 public MaxPQ(int maxN) { 9 pq = (Key[]) new Comparable[maxN+1]; 10 } 11 12 public boolean isEmpty(){ 13 return N == 0; 14 } 15 public int size(){ 16 return N; 17 } 18 public void insert(Key v){ 19 pq[++N] = v; 20 swim(N); 21 } 22 private void swim(int n) { 23 while(n > 1 && less(n/2,n)){ 24 exch(n/2,n); 25 n = n/2; 26 } 27 } 28 29 private boolean less(int i, int j) { 30 return pq[i].compareTo(pq[j]) < 0; 31 } 32 33 public Key delMax(){ 34 Key max = pq[1]; 35 exch(1,N--); 36 pq[N=1] = null; //防止对象游离 37 sink(1); 38 return max; 39 } 40 41 private void sink(int i) { 42 while(2 * i <= N){ 43 int j = 2*i; 44 if(j < N && less(j,j+1)) j++; 45 if(!less(i,j)) break; 46 exch(i,j); 47 i = j; 48 } 49 } 50 51 private void exch(int i, int j) { 52 Key t = pq[i]; 53 pq[i] = pq[j]; 54 pq[j] = t; 55 } 56 }