算法之最簡單的堆筆記

公共函數:

比較大小:

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

交換:

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

上浮: 當兒大於父,將兒不斷向上交換。初始化時一般從N/2位置開始

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


下沉: 當父小於兒,將父不斷向下。初始化時一般從1開始

private void sink(Array pq , int k){
    while (2*k <= N){        //N是pq.length
        int j = 2*k;
        if(j < N && less(j , j+1)) j++;
        if(!less(pq , k , j)) break;
        exch(pq , k , j);
        k = j;
    }
}


如圖:



概念:

每個節點都大於其子節點,這是堆的特性。所以當初始堆不符合這樣的特點時候,就需要進行堆的初始化。



堆的初始化:

1)堆初始化主要是滿足每個父節點大於等於子節點,而葉節點根本沒有子節點,所以不考慮葉節點

2)因爲不需要考慮葉節點,所以N/2位置一般爲截斷點

3)遇到不符合特點的節點,通過sink或者swim函數來調整

public void init(){          
    int N = a.length;
    for(int k = 1;k <= N/2;k++){
        sink(a , k)
    }
}



堆的添加:

1)把新增的節點放到最後

2)節點上浮到相應位置即可

public void insert (Array pq , Key v) {
    int N = pq.length;    
    pq[++N] = v;
    swim(pq , N);
}


堆的刪除:

1)把要刪除的元素與最後葉節點交換位置

2)被交換的葉節點進行下沉操作

3)把要刪除的元素爲null

public void del(int d , Array pq){
    Key del = pq[d];        
    int N = pq.length;
    exch(pq , d , N--); // 交換最後葉節點與要刪除元素位置
    sink(pq , d);       //下沉操作
    pq[N+1] = null;     //要刪除元素置null
}


堆的排序:

1)根節點與葉節點互換

2)下沉操作

3)原根節點刪除並存入新數組中

4)重複上面操作

while (N > 1) {
    exch(pq , 1 ,N--) ;    // 交換根和最大葉節點位置
    sink(pq , 1);          // 現在根節點下沉操作
}

發佈了72 篇原創文章 · 獲贊 51 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章