数据结构实现之最大优先队列(最大堆)
2016-01-23 00:40
399 查看
package xwq.dt; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import xwq.util.StdIn; import xwq.util.StdOut; /** ***************************************************************** **************** 最大优先队列API **************** 1、构造函数 public MaxPQ(); public MaxPQ(int capacity); public MaxPQ(Comparator cmp); public MaxPQ(int capacity,Comparator cmp); public MaxPQ(Key[] keys); public MaxPQ(Key[] keys,Comparator); 2、队列操作 public boolean isEmpty(); public int size(); public void push(Key key); 动态扩容*2 public Key pop(); public Key peek(); private void resize(int capacity); 3、堆辅助操作 private void adjustDown(int index); private void adjustUp(int index); private boolean less(Key k1,Key k2); private void swap(Key[] keys,int i,int j); ****************************************************************** */ public class MaxPQ<Key extends Comparable<Key>> implements Iterable<Key> { private Key[] keys; //关键字集合 private int N; //目前关键字容量 private Comparator comparator; //比较器 /** * 初始化空最大优先队列 */ public MaxPQ() { this(1); } /** * 初始化容量为capacity的最大优先队列 * @param capacity 容量 */ public MaxPQ(int capacity) { this(capacity,null); } /** * 初始化含有Key比较器的空最大优先队列 * @param cmp 自定义Key比较器 */ public MaxPQ(Comparator cmp) { this(1,cmp); } /** * 初始化含有Key比较器,容量为capacity的最大优先队列 * @param capacity 容量 * @param cmp Key比较器 */ public MaxPQ(int capacity,Comparator cmp) { keys = (Key[]) new Comparable[capacity+1]; this.comparator = cmp; N = 0; } /** * 初始化数组来自数组的最大优先队列 * @param keys 数组 */ public MaxPQ(Key[] keys) { this(keys,null); } /** * 初始化数组来自数组的最大优先队列,含有Key比较器 * @param keys 数组 * @param cmp Key比较器 */ public MaxPQ(Key[] ks,Comparator cmp) { this(ks.length,cmp); N = ks.length; for(int i = 1;i <= N;i++) keys[i] = ks[i-1]; for(int i=N/2 ;i >= 1;i--) adjustDown(i); } /**************************************************************** 队列操作 ****************************************************************/ /** * 判断队列是否为空 * @return */ public boolean isEmpty() { return N == 0; } /** * 获取队列大小 * @return */ public int size() { return N; } /** * 进队,向最大堆插入key * @param keys2 */ public void push(Key k) { //队列容量已满,扩容 if(N == keys.length-1) resize(N*2); keys[++N] = k; adjustUp(N); } /** * 出队,删除最大堆的根节点 * @return */ public Key pop() { if(isEmpty()) throw new NoSuchElementException("queue is empty."); Key max = keys[1]; swap(1,N--); adjustDown(1); keys[N+1]=null;//* 避免指针游走,以帮助尽快垃圾回收 if(N>0 && N == (keys.length-1)/4 ) resize((keys.length-1)/2); return max; } /** * 获取队首元素,最大堆的根节点 * @return */ public Key peek() { if(isEmpty()) throw new NoSuchElementException("queue is empty."); return keys[1]; } /** * 重定义堆容量大小 * @param capacity */ private void resize(int capacity) { assert capacity>N; Key[] news = (Key[]) new Comparable[capacity+1]; for(int i=1;i<=N;i++) news[i] = keys[i]; keys = news; } /**************************************************************** 堆辅助操作 ****************************************************************/ /** * 向下调整最大堆 * @param index 待调整堆起始索引 */ private void adjustDown(int index) { while(2*index <= N) { int l = index*2; //选择左右孩子节点中较大的一个 if(l<N && less(keys[l],keys[l+1])) l++; //判断index是否已经满足最大堆性质 if(less(keys[l],keys[index])) break; //向下调整 swap(index,l); index = l; } } /** * 向上调整最大堆 * @param index 待调整堆起始索引 */ private void adjustUp(int index) { while(index > 1) { int parent = index/2; //判断index是否已经满足最大堆性质 if(less(keys[index],keys[parent])) break; //向上调整 swap(index,parent); index = parent; } } /** * k1<k2 返回true * @param k1 * @param k2 * @return */ private boolean less(Key k1,Key k2) { if(this.comparator != null) return comparator.compare(k1, k2) < 0; else return ((Comparable)k1).compareTo(k2) < 0; } /** * 交换元素 * @param i * @param j */ private void swap(int i,int j) { Key t = keys[i]; keys[i] = keys[j]; keys[j] = t; } @Override public Iterator<Key> iterator() { return new HeapIterator(); } /*************************************************************************** * Iterator. ***************************************************************************/ /** * Returns an iterator that iterates over the keys on this priority queue * in descending order. * The iterator doesn't implement remove() since it's optional. * * @return an iterator that iterates over the keys in descending order */ private class HeapIterator implements Iterator<Key > { //创建一个新的最大优先队列 private MaxPQ<Key> copy; // copy堆中的所有元素 // 由于原顺序已满足堆性质,所以只需花费线性时间 public HeapIterator() { if(comparator == null) copy = new MaxPQ<Key>(N); else copy = new MaxPQ<Key>(N,comparator); for(int i=1;i<=N;i++) copy.push(keys[i]); } @Override public boolean hasNext() { return copy.size() > 0; } @Override public Key next() { if(copy.size() == 0) throw new NoSuchElementException("has not next element."); return copy.pop(); } @Override public void remove() { throw new UnsupportedOperationException("not support remove."); } } /** * Unit tests the MaxPriorityQueue data type. */ public static void main(String[] args) { MaxPQ<String> pq = new MaxPQ<String>(); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) pq.push(item); else if (!pq.isEmpty()) StdOut.print(pq.pop() + " "); } //使用迭代器 for(String s:pq) { StdOut.print(s+" "); } StdOut.println("(" + pq.size() + " left on pq)"); } }