package cn.xyc.sort.maxPQ;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
*
* 描述:索引优先队列
*
* <pre>
* HISTORY
* ****************************************************************************
* ID DATE PERSON REASON
* 1 2016年10月10日 蒙奇·D·许 Create
* ****************************************************************************
* </pre>
*
* @author 蒙奇·D·许
* @since 1.0
*/
public class IndexMaxPQ2<Key extends Comparable<Key>> {
/** 优先队列中索引的位置:queue_index ;queue代表队列中的下标位,index代表索引 */
private int queue_index[];// 存储索引i信息queue_index[n]=i;队列中只存储索引的位置
/** 索引在优先队列中的位置: index_queue[i]=n ;queue代表队列中的下标位,index代表索引 */
private int index_queue[];// 索引存储对应的n index_queue[i]=n;方便根据索引查询
/** 索引对应的数据:keys[index]=key */
private Key keys[];// 存储索引对应的具体的数据keys[index]=key;
private int n;// 队列中元素的个数
private int maxN;// 队列的最大长度
/**
* 初始化长度为maxN的数组
*
* @param MaxN
*/
@SuppressWarnings("unchecked")
public IndexMaxPQ2(int maxN) {
this.maxN = maxN;
this.n = 0;
this.queue_index = new int[maxN + 1];
this.index_queue = new int[maxN + 1];
keys = (Key[]) new Comparable[maxN + 1];
for (int i = 0; i <= maxN; i++)
index_queue[i] = -1;
}
/**
* 是否包含索引i
*
* @param i
* @return
*/
public boolean isContain(int i) {
return index_queue[i] != -1;
}
/**
* 判断是队列是否为空
*
* @return
*/
public boolean isEmpty() {
return this.n == 0;
}
/**
* 判断是否已经满了
*
* @return
*/
public boolean isFull() {
return this.n == this.maxN;
}
/**
* 返回队列的长度
*
* @return
*/
public int getSize() {
return this.n;
}
/**
* 得到最优的数据对应的索引
*
* @return
*/
public int getMaxOfIndex() {
if (n == 0)
throw new NoSuchElementException("Priority queue underflow");
return queue_index[1];
}
/**
* 得到索引优先队列中最大的Key
*
* @return
*/
public Key getMaxKey() {
if (n == 0)
throw new NoSuchElementException("Priority queue underflow");
return keys[queue_index[1]];
}
/**
* 判断i是否小于j
*
* @param i
* @param j
* @return
*/
private boolean less(int i, int j) {
return keys[queue_index[i]].compareTo(keys[queue_index[j]]) < 0;
}
/**
* 交换两个元素的位置
*
* @param i
* @param j
*/
private void exch(int i, int j) {
int swap = queue_index[i];
queue_index[i] = queue_index[j];
queue_index[j] = swap;
index_queue[queue_index[i]] = i;
index_queue[queue_index[j]] = j;
}
/**
* 当新插入、删除或者数据发生变大时,上浮
*
* @param k
*/
private void swim(int k) {
// 根据pq[k]找到索引,k>1等价于k/2>=1
while (k > 1 && less(k / 2, k)) {
exch(k / 2, k);
k = k / 2;
}
}
/**
* 当数据变小时,下沉
*
* @param k
*/
private void sink(int k) {
// 判断2*k和2*k+1的大小,选出其中较大者与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;
}
}
public void insert(int i, Key key) {
if (isContain(i))
throw new IllegalArgumentException(
"index is already in the priority queue");
n++;
index_queue[i] = n;
queue_index[n] = i;
keys[i] = key;
swim(n);
}
/**
* 删除
*
* @return
*/
public int delMax() {
if (n == 0)
throw new NoSuchElementException("Priority queue underflow");
int min = queue_index[1];
exch(1, n--);// 交换最后一个元素的位置,并将n减一
sink(1);
assert queue_index[n + 1] == min;
index_queue[min] = -1; // delete
keys[min] = null; // to help with garbage collection
queue_index[n + 1] = -1; // not needed
return min;
}
/**
* 根据索引拿到数据
*
* @param i
* @return
*/
public Key keyOf(int i) {
if (!isContain(i))
throw new NoSuchElementException(
"index is not in the priority queue");
else
return keys[i];
}
/**
* 改变索引的值
*
* @param i
* @param key
*/
public void changeKey(int i, Key key) {
if (!isContain(i))
throw new NoSuchElementException(
"index is not in the priority queue");
keys[i] = key;
swim(index_queue[i]);
sink(index_queue[i]);
}
public void increaseKey(int i, Key key) {
if (!isContain(i))
throw new NoSuchElementException(
"index is not in the priority queue");
if (keys[i].compareTo(key) >= 0)
throw new IllegalArgumentException(
"Calling increaseKey() with given argument would not strictly increase the key");
keys[i] = key;
swim(index_queue[i]);
}
public void decreaseKey(int i, Key key) {
if (!isContain(i))
throw new NoSuchElementException(
"index is not in the priority queue");
if (keys[i].compareTo(key) <= 0)
throw new IllegalArgumentException(
"Calling decreaseKey() with given argument would not strictly decrease the key");
keys[i] = key;
sink(index_queue[i]);
}
@SuppressWarnings("unused")
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>(queue_index.length - 1);
for (int i = 1; i <= n; i++)
copy.insert(queue_index[i], keys[queue_index[i]]);
}
public boolean hasNext() {
return !copy.isEmpty();
}
public void remove() {
throw new UnsupportedOperationException();
}
public Integer next() {
if (!hasNext())
throw new NoSuchElementException();
return copy.delMax();
}
}
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> queue_index = new IndexMaxPQ<String>(strings.length);
for (int i = 0; i < strings.length; i++) {
queue_index.insert(i, strings[i]);
}
// print each key using the iterator
for (int i : queue_index) {
System.out.println(i + " " + strings[i]);
}
System.out.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 (!queue_index.isEmpty()) {
String key = queue_index.maxKey();
int i = queue_index.delMax();
System.out.println(i + " " + key);
}
System.out.println();
// reinsert the same strings
for (int i = 0; i < strings.length; i++) {
queue_index.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 = queue_index.keyOf(perm[i]);
queue_index.delete(perm[i]);
System.out.println(perm[i] + " " + key);
}
}
}
java数据结构和算法(IndexMaxPQ2)
最新推荐文章于 2024-01-06 20:54:30 发布