資料結構實現之最小優先佇列(最小堆)
阿新 • • 發佈:2019-01-31
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+" ");
}
}