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 MinPQ();
public MinPQ(int capacity);
public MinPQ(Comparator cmp);
public MinPQ(int capacity,Comparator cmp);
public MinPQ(Key[] keys);
public MinPQ(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 MinPQ<Key extends Comparable<Key>> implements Iterable<Key > {
private Key[] pq;
private int N;
private Comparator comparator;
//默认构造函数
public MinPQ() {
this(1);
}
//初始化空的最小优先队列,给定初始容量
public MinPQ(int capacity) {
this(capacity,null);
}
//初始化具有比较器的最小优先队列
public MinPQ(Comparator cmp) {
this(1,null);
}
//初始化具有比较器和初始容量的最小优先队列
public MinPQ(int capacity,Comparator cmp) {
pq = (Key[])new Comparable[capacity+1];
N = 0;
comparator = cmp;
}
//初始化给定数组的最小优先队列
public MinPQ(Key[] keys) {
this(keys,null);
}
//初始化给定数组以及比较器的最小优先队列
public MinPQ(Key[] keys,Comparator cmp) {
this(keys.length,cmp);
N = keys.length;
for(int i=0;i<keys.length;i++)
pq[i] = keys[i];
for(int i=N/2;i>=1;i--)
adjustDown(i);
}
/**
* 判断最小优先队列是否为空
* @return
*/
public boolean isEmpty() {
return N == 0;
}
/**
* 获取目前最小优先队列中所存储元素的个数
* @return
*/
public int size() {
return N;
}
/**
* 入队,插入元素到最小优先队列
* @param key
*/
public void push(Key key) {
//如果当前队列容量已满,扩充队列
if(N == pq.length-1)
resize(2*N);
pq[++N] = key;
adjustUp(N);
}
/**
* 出队,删除最小优先队列的队头元素
* @return
*/
public Key pop() {
if(isEmpty())
throw new NoSuchElementException("MinPQ has empty.");
Key min = pq[1];
swap(1,N--);
adjustDown(1);
pq[N+1] = null;//防止被删除位置元素指针不稳定,以便垃圾收集的执行
//如果队列容量为所存储元素个数的四倍,缩小队列使用容量
if( N == (pq.length-1)/4 )
resize((pq.length-1)/2);
return min;
}
/**
* 获取最小优先队列的队头元素
* @return
*/
public Key peek() {
if(isEmpty())
throw new NoSuchElementException("MinPQ has empty.");
return pq[1];
}
/**
* 返回MinPQ的迭代器
*/
@Override
public Iterator<Key> iterator() {
return new HeapIterator();
}
/**
* 重新定义队列容量
* @param capacity
*/
private void resize(int capacity) {
assert N < capacity;
Key[] news = (Key[])new Comparable[capacity+1];
for(int i = 1 ;i <= N ;i++)
news[i] = pq[i];
pq = news;
}
/**
* 向下调整堆
* @param index
*/
private void adjustDown(int index) {
while(2*index<=N) {
int l = 2*index;//index的左孩子
//如果有右孩子,且右孩子小于左孩子,选择右孩子
if(l<N && greater(l,l+1))
l++;
//比较index与孩子的大小
//如果index比孩子小,则已满足最小堆性质,结束
if(greater(l,index))
break;
//否则交换index与孩子的值,继续向下迭代
swap(l,index);
index = l;
}
}
/**
* 向上调整堆
* @param index
*/
private void adjustUp(int index) {
while(index>1) {
int p = index/2;
//index比父母值大,满足最小堆性质,结束
if(greater(index,p))
break;
//否则交换index与其父母的值,继续向上迭代
swap(index,p);
index = p;
}
}
/**
* 判断队列中的pq[i],pq[j]的大小
* @param i pq[i]
* @param j pq[j]
* @return pq[i]>pq[j] 返回true
*/
private boolean greater(int i,int j) {
if(comparator != null)
return comparator.compare(pq[i], pq[j]) > 0;
else
return ((Comparable)pq[i]).compareTo(pq[j]) > 0;
}
/**
* 交换队列中的pq[i],pq[j]元素值
* @param i pq[i]
* @param j pq[j]
*/
private void swap(int i,int j) {
Key t = pq[i]; pq[i] = pq[j]; pq[j] = t;
}
/**
* MinPQ的迭代器,因为操作关系所以不支持删除操作
*/
private class HeapIterator implements Iterator<Key> {
//创建一个新的最小优先队列
private MinPQ<Key> copy;
// copy堆中的所有元素
// 由于原顺序已满足堆性质,所以只需花费线性时间
public HeapIterator() {
if(comparator == null)
copy = new MinPQ(N);
else
copy = new MinPQ(N,comparator);
for(int i=1;i<=N;i++)
copy.push(pq[i]);
}
@Override
public boolean hasNext() {
return copy.size() > 0;
}
@Override
public Key next() {
if(copy.size() <=0 )
throw new NoSuchElementException("MinPQ has empty.");
return copy.pop();
}
@Override
public void remove() {
throw new UnsupportedOperationException("iterator do not support remove operation.");
}
}
public static void main(String[] args) {
MinPQ<String > pq = new MinPQ<String>();
while(!StdIn.isEmpty()) {
String s = StdIn.readString();
if(!s.equals("-"))
pq.push(s);
else if(!pq.isEmpty())
StdOut.print(pq.pop()+" ");
}
StdOut.println("size:"+pq.size());
for(String s:pq)
StdOut.print(s+" ");
}
}
数据结构实现之最小优先队列(最小堆)
最新推荐文章于 2022-05-26 11:08:03 发布