数据结构实现之最大索引优先队列
2016-01-24 17:25
519 查看
具体索引优先队列的说明见数据结构实现之最小优先队列
package xwq.dt; import java.util.Iterator; import java.util.NoSuchElementException; import xwq.util.StdOut; import xwq.util.StdRandom; /** * 使用二叉堆实现的索引最大优先队列 * class IndexMaxPQ是一个支持泛型的索引优先队列。 * IndexMaxPQ支持普通的insert、delete-the-maximum、delete以及change-the-key方法。 * 用户可以使用队列中的0到maxN-1号索引执行删除和修改方法。 * IndexMaxPQ支持获取队列最小元素,队列最小元素索引操作。 * IndexMaxPQ支持迭代器迭代所有插入的索引号。 * * IndexMaxPQ的实现使用二叉堆。 * The <em>insert</em>, <em>delete-the-maximum</em>, <em>delete</em>, * <em>change-key</em>, <em>decrease-key</em>, and <em>increase-key</em> * 操作时间复杂度为O(lgN). * The <em>is-empty</em>, <em>size</em>, <em>min-index</em>, <em>min-key</em>, and <em>key-of</em> * operations 时间复杂度为O(1). * @author xwq * * @param <Key> */ public class IndexMaxPQ <Key extends Comparable<Key>> implements Iterable<Integer>{ private int maxN;//索引优先队列中元素的最大个数 private int N;//当前索引优先队列中元素的个数 private int[] pq;//使用一级索引的二叉堆 private int[] qp;//pq的对称映射 qp[pq[i]] = pq[qp[i]] = i,用于映射key索引对应pq二叉堆中的位置 private Key[] keys;//keys[i] = priority of i /** * 初始化索引区间为(0到maxN-1)的空索引优先队列 * @param capacity */ public IndexMaxPQ(int capacity) { if(capacity<=0) throw new IllegalArgumentException(); maxN = capacity; N = 0; pq = new int[capacity+1]; qp = new int[capacity+1]; keys = (Key[])new Comparable[capacity+1]; //初始每个索引都没用过 for(int i=0;i<=maxN;i++) qp[i] = -1; } /** * 如果队列为空返回true * @return 如果队列为空返回true,否则返回false */ public boolean isEmpty() { return N == 0; } /** * 队列的当前元素个数 * @return 队列的当前元素个数 */ public int size() { return N; } /** * 判断优先队列是否已存在索引i * @param i 索引i * @return 如果索引i之前已插入,返回true,否则false */ public boolean contains(int i) { return qp[i] != -1; } public Key maxKey() { if(N == 0) throw new NoSuchElementException("IndexMaxPQ was underflow."); return keys[pq[1]]; } /** * 返回最大键值的索引号 * @return 最大键值的索引号 */ public int maxIndex() { if(N == 0) throw new NoSuchElementException("IndexMaxPQ was underflow."); return pq[1]; } /** * 返回优先队列最小值,即二叉堆根节点 * @return 优先队列最小值 */ public Key keyOf(int i) { if(i<0 || i>=maxN) throw new IndexOutOfBoundsException(); if(!contains(i)) throw new IllegalArgumentException("i not exists in IndexMaxPQ"); return keys[i]; } /** * 将索引i与键值key关联 * @param i 索引i * @param key 键值key */ public void insert(int i,Key key) { if(i<0 || i>=maxN) throw new IllegalArgumentException(); if(contains(i)) throw new IllegalArgumentException("index i has existed"); N++; qp[i] = N; pq = i; keys[i] = key; adjustUp(N); } /** * 删除最大键值并返回其对应的索引 * @return 最大键值对应的索引 */ public int delMax() { if(N == 0) throw new NoSuchElementException("IndexMaxPQ was underflow."); int max = pq[1]; swap(1,N--); adjustDown(1); qp[max] = -1; keys[max] = null; pq[N+1] = -1; return max; } /** * 删除索引i以及其对应的键值 * @param i 待删除的索引i */ public void delete(int i) { if(i<0 || i>=maxN) throw new IllegalArgumentException(); if(!contains(i)) throw new NoSuchElementException("IndexMaxPQ not existe index i."); int index = qp[i]; swap(index,N--); adjustUp(index); adjustDown(index); qp[i] = -1; keys[i] = null; pq[N+1] = -1; } /** * 改变与索引i关联的键值 * @param i 待改变键值的索引 * @param key 改变后的键值 */ public void changeKey(int i,Key key) { if(i<0 || i>=maxN) throw new IllegalArgumentException(); if(!contains(i)) throw new NoSuchElementException("IndexMaxPQ not existe index i."); if(keys[i] == key) throw new IllegalArgumentException("key equal to will be changed value"); if(keys[i].compareTo(key)<0) increaseKey(i,key); //key比原来的key值大 else decreaseKey(i,key);//key比原来的key值小 } /** * 减小与索引i关联的键值到给定的新键值 * @param i 与待减小的键值关联的索引 * @param key 新键值 */ public void decreaseKey(int i,Key key) { if(i<0 || i>=maxN) throw new IllegalArgumentException(); if(!contains(i)) throw new NoSuchElementException("IndexMaxPQ not existe index i."); if(keys[i].compareTo(key)<=0) throw new IllegalArgumentException("Calling decreaseKey() with given argument would not strictly decrease the key"); keys[i] = key; adjustDown(qp[i]); } /** * 增加与索引i关联的键值到给定的新键值 * @param i 与待增加的键值关联的索引 * @param key 新键值 */ public void increaseKey(int i,Key key) { if(i<0 || i>=maxN) throw new IllegalArgumentException(); if(!contains(i)) throw new NoSuchElementException("IndexMaxPQ not existe index i."); if(keys[i].compareTo(key)>=0) throw new IllegalArgumentException("Calling increaseKey() with given argument would not strictly increase the key"); keys[i] = key; adjustUp(qp[i]); } /*************************************************************************** * General helper functions. ***************************************************************************/ /** * 交换一级索引值,以及其对称映射中的值 * @param i 使用一级索引的二叉堆的索引i * @param j 使用一级索引的二叉堆的索引j */ private void swap(int pqi,int pqj) { int t = pq[pqi]; pq[pqi] = pq[pqj]; pq[pqj] = t; qp[pq[pqi]] = pqi; qp[pq[pqj]] = pqj; } /** * 判断键值的大小关系 * @param pqi 使用一级索引的二叉堆的索引i * @param pqj 使用一级索引的二叉堆的索引j * @return keys[ki] < keys[kj] 返回true,否则返回false */ private boolean less(int pqi,int pqj) { int ki = pq[pqi]; int kj = pq[pqj]; return keys[ki].compareTo(keys[kj]) < 0; } /*************************************************************************** * Heap helper functions. ***************************************************************************/ /** * 向下调整最大二叉堆 * @param i 一级索引的二叉堆的索引i,pq数组的数组位置 */ private void adjustDown(int i) { while(2*i <= N) { int l = 2*i; if(l<N && less(l,l+1)) l++; //已满足最大堆性质,自身的值大于左右两节点的值 if(less(l,i)) break; swap(l,i); i = l; } } /** * 向上调整最大二叉堆 * @param i 一级索引的二叉堆的索引i,pq数组的数组位置 */ private void adjustUp(int i) { while(i>1) { int p = i/2; //自身元素值小于父元素值,满足最大堆性质,返回 if(less(i,p)) break; swap(i,p); i = p; } } @Override public Iterator<Integer> iterator() { // TODO Auto-generated method stub return new HeapIterator(); } /*************************************************************************** * Iterators. ***************************************************************************/ /** * Returns an iterator that iterates over the keys on the * priority queue in descending order. * The iterator doesn't implement <tt>remove()</tt> since it's optional. * * @return an iterator that iterates over the keys in ascending order */ private class HeapIterator implements Iterator<Integer>{ // create a new pq private IndexMaxPQ<Key> copy; // add all elements to copy of heap // takes linear time since already in heap order so no keys move public HeapIterator() { copy = new IndexMaxPQ<Key>(maxN); for(int i=1;i<=N;i++) copy.insert(pq[i],keys[pq[i]]); } @Override public boolean hasNext() { return !copy.isEmpty(); } @Override public Integer next() { if(copy.isEmpty()) throw new NoSuchElementException(); return copy.delMax(); } @Override public void remove() { throw new UnsupportedOperationException(); } } /** * Unit tests the <tt>IndexMaxPQ</tt> data type. */ public static void main(String[] args) { // insert a bunch of strings String[] strings = { "it", "was", "the", "best", "of", "times", "it", "was", "the", "worst" }; IndexMaxPQ<String> pq = new IndexMaxPQ<String>(strings.length); for (int i = 0; i < strings.length; i++) { pq.insert(i, strings[i]); } StdOut.print(); // print each key using the iterator for (Integer i : pq) { StdOut.println(i + " " + strings[i]); } StdOut.println(); // increase or decrease the key for (int i = 0; i < strings.length; i++) { if (StdRandom.uniform() < 0.5) pq.increaseKey(i, strings[i] + strings[i]); else pq.decreaseKey(i, strings[i].substring(0, 1)); } // delete and print each key while (!pq.isEmpty()) { String key = pq.maxKey(); int i = pq.delMax(); StdOut.println(i + " " + key); } StdOut.println(); // reinsert the same strings for (int i = 0; i < strings.length; i++) { pq.insert(i, strings[i]); } // delete them in random order int[] perm = new int[strings.length]; for (int i = 0; i < strings.length; i++) perm[i] = i; StdRandom.shuffle(perm); for (int i = 0; i < perm.length; i++) { String key = pq.keyOf(perm[i]); pq.delete(perm[i]); StdOut.println(perm[i] + " " + key); } } }
相关文章推荐
- 数据结构实现之最小索引优先队列
- Eigen库数据结构内存对齐问题
- 【Redis笔记(四)】 Redis数据结构 - list链表
- HDU1022 Train Problem I 数据结构
- 数据结构与算法——在一个数组中实现两个堆栈(C语言)
- 数据结构实验之栈三:后缀式求值
- 已知后序中序序列求先序序列
- 对于二叉树三种非递归遍历方式的理解
- 2015年大二上-数据结构-图-1-(3)图遍历算法实现
- 优先队列——斐波那契堆(without source code)
- 2015年大二上-数据结构-图-1-(2)操作用邻接表存储的图
- 一个程序猿学生寒假自我修养
- 返回某集合的所有子集
- 快速掌握Lua 5.3 —— 数据结构
- 数据结构笔记之绪论
- ZMQ源码分析(一)-- 基础数据结构的实现
- LinkedList各种操作
- Lua学习笔记-数据结构
- 数据结构之--图的讲解与C语言实现
- 合并果子(贪心+优先队列)