最小最大堆(双端堆)的实现(Java版)
2012-06-21 13:25
495 查看
最小最大堆是同时实现最小堆和最大堆的一种数据结构。具有以下操作功能:
(1)插入操作(O(logN));
(2)返回最小值(O(1)),返回最大值(O(1));
(3)删除最小值(O(logN)),删除最大值(O(logN))。
最小最大堆的根结点是堆中的最小值。把根结点看做是第一层的话,奇数层是最小堆层,也是这些奇数层实现的是最小堆结构,同样,偶数层是最大堆层,偶数层实现最大堆结构。下图为为一最小最大堆
(1)插入操作(O(logN));
(2)返回最小值(O(1)),返回最大值(O(1));
(3)删除最小值(O(logN)),删除最大值(O(logN))。
最小最大堆的根结点是堆中的最小值。把根结点看做是第一层的话,奇数层是最小堆层,也是这些奇数层实现的是最小堆结构,同样,偶数层是最大堆层,偶数层实现最大堆结构。下图为为一最小最大堆
package com.ldl.algorithms.Exercise; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import com.ldl.algorithms.StdIn; import com.ldl.algorithms.StdOut; public class Min_MaxHeap<Key> implements Iterable<Key> { private Key[] pq; //store items at indices 1 to N private int N; //number of items on priority queue private Comparator<Key> comparator; //optional comparator /** * Create an empty priority queue with the given initial capacity. */ public Min_MaxHeap(int initCapacity) { pq = (Key[])new Object[initCapacity + 1]; N = 0; } /** * Create an empty priority queue. */ public Min_MaxHeap() { this(1); } /** * Create an empty priority queue with the given initial capacity, * using the given comparator. */ public Min_MaxHeap(int initCapacity, Comparator<Key> comparator) { this.comparator = comparator; pq = (Key[])new Object[initCapacity + 1]; N = 0; } /** * Create an empty priority queue using the given comparator. */ public Min_MaxHeap(Comparator<Key> comparator) { this(1, comparator); } /** * Create a priority queue with the given items. * Takes time proportional to the number of items using sink-based heap construction. */ public Min_MaxHeap(Key[] keys) { N = keys.length; pq = (Key[]) new Object[N + 1]; for(int i = 0; i < N; i++) pq[i+1] = keys[i]; for(int k = N/2; k>=1; k--) sink(k); assert isMin_MaxHeap(); } /** * Is the priority queue empty? */ public boolean isEmpty() { return N == 0; } /** * Return the number of items on the priority queue. */ public int size(){ return N; } /** * Return the smallest key on the priority queue. * Throw an exception if no such key exists because the priority queue is empty. */ public Key min() { if(isEmpty()) throw new RuntimeException("Priority queue underflow"); return pq[1]; } /** * Return the largest key on the priority queue. * Throw an exception if no such key exists because the priority queue is empty. */ public Key max() { if(N == 0) throw new RuntimeException("Priority queue underflow"); if(N == 1) return pq[1]; if(N == 2) return pq[2]; return less(1, 2) ? pq[2] : pq[1]; } /** * Add a new key to the priority queue. */ public void insert(Key x) { if (N == pq.length - 1) resize(2 * pq.length); pq[++N] = x; swim(N); assert isMin_MaxHeap(); } /** * Delete and return the smallest key on the priority queue. * Throw an exception if no such key exists because the priority queue is empty. */ public Key delMin() { if(N == 0) throw new RuntimeException("Priority queue underflow"); exch(1, N); Key min = pq[N--]; sink(1); pq[N+1] = null; if ((N > 0) && (N == (pq.length - 1) / 4)) resize(pq.length / 2); assert isMin_MaxHeap(); return min; } /** * Delete and return the largest key on the priority queue. * Throw an exception if no such key exists because the priority queue is empty. */ public Key delMax() { if(N == 0) throw new RuntimeException("Priority queue underflow"); if(N == 1) return delMin(); if(N == 2) { Key max =pq[2]; N--; pq[N+1] = null; if ((N > 0) && (N == (pq.length - 1) / 4)) resize(pq.length / 2); return max; } int m = less(2, 3) ? 3 : 2; exch(m, N); Key max = pq[N--]; sink(m); pq[N+1] = null; if ((N > 0) && (N == (pq.length - 1) / 4)) resize(pq.length / 2); return max; } //helper function to double the size of the heap array private void resize(int capacity) { Key[] temp = (Key[]) new Object[capacity]; for(int i = 1; i <= N; i++) temp[i] = pq[i]; pq = temp; } /*********************************************************************** * Helper functions to restore the heap invariant. **********************************************************************/ private void sink(int k) { if(isMin(k)) sinkMin(k); else sinkMax(k); } private void sinkMin(int k) { if(2*k <= N) { int m; if(4*k > N) { if(N == 2*k) m = 2*k; else m = less(2*k, 2*k+1) ? 2*k : 2*k+1; if(less(m, k)) exch(m, k); } else { m = 4*k; for(int i = 4*k+1; i <= N && i < 4*k+4; i++) if(less(i, m)) m = i; if(less(m, k)) { exch(m, k); if(less(m/2, m)) exch(m/2, m); sinkMin(m); } } } } private void sinkMax(int k) { if(2*k <= N) { int m; if(4*k > N) { if(N == 2*k) m = 2*k; else m = less(2*k, 2*k+1) ? 2*k+1 : 2*k; if(less(k, m)) exch(m, k); } else { m = 4*k; for(int i = 4*k+1; i <= N && i < 4*k+4; i++) if(less(m, i)) m = i; if(less(k, m)) { exch(m, k); if(less(m, m/2)) exch(m/2, m); sinkMax(m); } } } } private void swim(int k) { if(isMin(k)) { if(k > 1 && less(k/2, k)) { exch(k, k/2); swimMax(k/2); } else swimMin(k); } else { if(k > 1 && less(k, k/2)) { exch(k, k/2); swimMin(k/2); } else swimMax(k); } } private void swimMin(int k) { if(k/4 > 0 && less(k, k/4)) { exch(k, k/4); swimMin(k/4); } } private void swimMax(int k) { if(k/4 > 0 && less(k/4, k)) { exch(k, k/4); swimMax(k/4); } } private boolean less(int i, int j) { if (comparator == null) { return ((Comparable<Key>) pq[i]).compareTo(pq[j]) < 0; } else { return comparator.compare(pq[i], pq[j]) < 0; } } private void exch(int i, int j) { Key swap = pq[i]; pq[i] = pq[j]; pq[j] = swap; } // is node k is on min level? private boolean isMin(int k) { double r = Math.log((double)(k + 1)) / Math.log(2.0); int floor = (int)Math.ceil(r); return (floor & 1) == 1; } // is pq[1..N] a min-max heap? private boolean isMin_MaxHeap() { return isMin_MaxHeap(1); } // is subtree of pq[1..N] rooted at k a min-max heap? private boolean isMin_MaxHeap(int k) { if (k > N) return true; int left = 2*k, right = 2*k + 1; if(isMin(k)) { if (left <= N && less(left, k)) return false; if (right <= N && less(right, k)) return false; } else { if (left <= N && less(k, left)) return false; if (right <= N && less(k, right)) return false; } return isMin_MaxHeap(left) && isMin_MaxHeap(right); } /*********************************************************************** * Iterators **********************************************************************/ /** * Return an iterator that iterates over all of the keys on the priority queue * in ascending order. * <p> * The iterator doesn't implement <tt>remove()</tt> since it's optional. */ public Iterator<Key> iterator() { return new Min_MaxHeapIterator(); } private class Min_MaxHeapIterator implements Iterator<Key> { // create a new pq private Min_MaxHeap<Key> copy; // add all items to copy of heap // takes linear time since already in heap order so no keys move public Min_MaxHeapIterator() { if(comparator == null) copy = new Min_MaxHeap<Key>(size()); else copy = new Min_MaxHeap<Key>(size(), comparator); for(int i = 1; i <= N; i++) copy.insert(pq[i]); } public boolean hasNext() {return !copy.isEmpty();} public void remove() { throw new UnsupportedOperationException(); } public Key next() { if (!hasNext()) throw new NoSuchElementException(); return copy.delMin(); } } /** * A test client. */ public static void main(String[] args) { Min_MaxHeap<String> pq = new Min_MaxHeap<String>(); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("+") && !item.equals("-")) pq.insert(item); else if (!pq.isEmpty() && item.equals("+")) StdOut.print(pq.delMax() + " "); else if (!pq.isEmpty() && item.equals("-")) StdOut.print(pq.delMin() + " "); } } }
相关文章推荐
- java递归实现最大公约数和最小公倍数
- java 使用面向对象方式实现录入学生信息,取出成绩最大值、最小值、平均值、对其进行排序
- java实现栈-输出最大值,最小值,时间复杂度O(1)
- Java实现最小公倍数和最大公约数
- c++/java/python priority_que实现最大堆和最小堆
- java代码--实现随机输出10个随机数,并显示最大值,最小值
- java中数据类型间的最大值,最小值及转换程序代码实现
- 数组求最大最小值和排序java实现
- java实现查找List集合中的最大值和最小值
- 读《程序员编程艺术》之自造Java版本----最大堆排序实现最小K问题
- 基于Tire树和最大概率法的中文分词功能的Java实现
- 自己想出来的,用静态内部类实现一次遍历求数组元素的最大值和最小值的方法
- 【LeetCode-面试算法经典-Java实现】【064-Minimum Path Sum(最小路径和)】
- java:最小公倍数和最大公约数
- java基础_day0018_数组_ArrayUtil_最大值_最小值_交换_复制_平均值_求和
- 最小-最大堆的实现
- JAVA 数组实例-求学生成绩的最大成绩,获取数组中的最大值、最小值
- Java数组的应用2:数组的最大,最小,求和,平均值,倒置
- 腾讯笔试之M*N矩阵 左对角到右对角最大值 java实现
- java二维数组求每行最大值,每列最小值,及输出数组主对角线上的元素