1. 程式人生 > >用有序二叉堆實現優先佇列

用有序二叉堆實現優先佇列

優先佇列

優先佇列要提供並實現兩個操作

  • 刪除並返回最大元素
  • 插入元素

優先佇列的實現

優先佇列的實現採用有序二叉堆形式,採用連結串列或堆疊也可實現,但時間複雜度較高。這裡不再贅述。

有序二叉堆的特點

  • 所有根結點必定不小於其兩個葉子節點
  • 如果某個節點對應的陣列下標為k,則其根節點為k/2,其葉子節點為2k和2k+1
  • 有序二叉堆通過陣列實現,採用陣列a[N+1]描述有序二叉堆中第一個到最後一個節點(陣列元素a[0]不使用,從a[1]開始)。
  • 如圖所示:
    這裡寫圖片描述

有序二叉堆的主要操作

  • 上浮
    插入新元素到堆中時,先將該元素置於陣列末尾,再上浮至正確節點
  • 下沉
    移除
    根節點元素時(假設根節點為最大元素),將陣列末尾元素置於根節點,再下沉至正確位置
public class MaxPQ<T extends Comparable<T>>{
    private T[] a;
    private int index= 0;//指向末尾元素
    private int N;//記錄陣列的大小

    public MaxPQ(int size){
        N = size;
        a = (T[])new Comparable[](size + 1);
    }
    //插入新元素到堆中
    public void
insert(T item){ //插入前檢測陣列是否需要擴容 if (index >= N * 0.75) { resize(a); N = a.length; } //指標指向新的末尾元素 a[++index] = item; //上浮至正確節點位置 swim(index); } private void swim(int k){ while(k > 1 && a[k] > a[k/2
]){ swap(k, k/2); k = k / 2;//每上浮一次,k要變為其父節點位置 } } //從堆中移除最大元素 private T removeMax(){ T max = a[1]; a[1] = a[index];//將末尾元素當作新的根節點 a[index] = null;//防止物件遊離 index--; sink(1);//將根節點元素下沉至正確位置 return max; } private T sink(int k){ while(k* 2 < N){ int j = 2 * k;//j記錄葉子節點位置 if (a[j] < a[j+1]) {j++};//j移動到兩個葉子節點中較大的那個 if (a[k] > a[j]) {break};//如果父節點大於葉子節點,說明位置已找到,跳出迴圈 swap(k, j);//否則將父節點和葉子節點交換 k = j; } } //陣列擴容函式 private void resize(T[] a){ T[] temp = (T[])new Object[N * 2]; for (int i = 0; i < a.length; i++) { temp[i] = a[i]; } a = temp; } }