《Algorithms算法》筆記:優先隊列(2)——二叉堆

二叉堆

1 二叉堆的定義

堆是一個徹底二叉樹結構(除了最底下一層,其餘層全是徹底平衡的),若是每一個結點都大於它的兩個孩子,那麼這個堆是有序的。java

二叉堆是一組可以用堆有序的徹底二叉樹排序的元素,並在數組中按照層級存儲(不用數組的第一個位置)
node

 

2 二叉堆的性質

  • 最大的元素在a[1] (root結點)
  • 每一個k的父親在k/2
  • 每一個k的孩子在k*2和k*2+1

3 二叉堆的操做

3.1 上浮(孩子大於父親)——對應插入操做

循環,每次比較本身和父親,若是比父親大就交換,直到root。
算法

 

3.2 插入

先把元素加入數組的最後一個位置,而後進行上浮到正確位置
數組

 

3.3 下沉(父親小於兒子)——對應刪除操做

循環,每次比較本身和兩個孩子,若是比孩子小就交換,若是比兩個孩子都小,就交換到兩個裏面較大的一個。直到葉子。
markdown

 

3.4 刪除最大元素

先把根元素與最後一個元素交換,刪除最後一個元素,而後從根開始下沉到正確位置。less

 

4 二叉堆優先隊列代碼

/** * * @author rocky */
public class MaxPQ<Key extends Comparable<Key>> {

    private Key[] pq;
    private int N;

    public MaxPQ(int capacity) {
        pq = (Key[]) new Comparable[capacity + 1];
    }

    public boolean isEmpty() {
        return N == 0;
    }

    public void insert(Key key)
    {      
        N++; 
        pq[N] = key;
        swim(N);
    }

    public Key delMax() {
        Key max = pq[1];  //get the max element
        exch(1, N);     //exchange between the root and the last element
        N--;   
        sink(1);   //sink to the right place
        pq[N+1] = null;   //delete
        return max;
    }

    private void swim(int k)
    {
        while(k > 1 && less(k/2, k))
        {
            exch(k, k/2);
            k /= 2;
        }

    }

    private void sink(int k) {
        while(k*2 <= N)    //if this node has left child 
        {
            int child = k * 2;   
            if (child < N && less(child, child + 1)) {  //if the left child is less than the right child
                child = child + 1;   //change child to the right child
            }
            if (less(k, child)) {
                exch(k, child);
            }
            k = child;
        }
    }

    private boolean less(int i, int j) {
        return pq[i].compareTo(pq[j]) < 0;
    }

    private void exch(int i, int j) {
        Key t = pq[i];
        pq[i] = pq[j];
        pq[j] = t;
    }
}

5 二叉堆擴展

 

 

5.1 不可變性

咱們算法的前提是用戶不會改變隊列的元素,若是用戶能改變隊列的元素,那麼隊列成立的條件就會破壞,
不可變的數據類型,就是說一個實例一旦創建,就不能夠改變。java裏不少類型都是不可變的。
this

 

這有不少好處,可是壞處就是若是你須要改變值必需要新建一個對象。
spa

相關文章
相關標籤/搜索