您的位置:首页 > 理论基础 > 数据结构算法

数据结构实现之最大优先队列(最大堆)

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)");
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: