1. 程式人生 > >資料結構實現之最小優先佇列(最小堆)

資料結構實現之最小優先佇列(最小堆)

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