堆排代碼筆記

搞了個HeapSort類,有個類變量type肯定是大頂堆仍是小頂堆。算法

注意,用堆的時候處理的數組是0元素不用的!!數組

 

上代碼:this

package www.com.leetcode.specificProblem;

/**
 * 數組的0元素不用
 * @author 85060
 *
 */
public class HeapSort {
    
    private int heapType;//0表示大頂堆,其餘都是小頂堆
    
    public HeapSort(int heapType) {
        this.heapType = heapType;
    }
    
    public void heapSort(int[] num) {
        makeHeap(num);
        
        for(int i = num.length - 1; i >= 2; i--) {//這個i能夠理解成,要和堆頂元素交換的那個index,確定到2就結束了
            shiftDown(num, 1, i);
            
            //堆頂和堆最後的元素交換
            int temp = num[1];
            num[1] = num[i];
            num[i] = temp;
        }
    }
    
    /**
     * 這個方法把傳進來的數組變成堆
     * @param num
     */
    public void makeHeap(int[] num) {
        for(int i = (num.length - 1)/2; i >= 1; i--) {//從最後一個有孩子的結點開始,作篩選操做,直到根節點也就是1號元素(0號不用)
            shiftDown(num, i, num.length - 1);
        }
    }
    
    
    /**
     * 將一顆樹從上到下篩選成堆的方法,前提這個根的兩個子樹都已是堆了
     * @param heap
     * @param root 開始的結點,也就是根
     * @param last 結束的結點,或者說是徹底二叉樹最後的那個結點
     */
    public void shiftDown(int[] heap, int root, int last) {
        int rootIndexTemp = root;
        int leftIndexTemp, rightIndexTemp, priorChildIndexTemp;
        
        while(2 * rootIndexTemp <= last) {//保證temp表示的樹的左孩子在範圍以內
            leftIndexTemp = 2 * rootIndexTemp;
            rightIndexTemp = 2 * rootIndexTemp + 1;
            
            if(rightIndexTemp > last)priorChildIndexTemp = leftIndexTemp;//沒有右孩子,那麼孩子之間的優先者就直接左孩子
            else priorChildIndexTemp = prior(heap[leftIndexTemp], heap[rightIndexTemp]) ? leftIndexTemp : rightIndexTemp;
            
            if(prior(heap[rootIndexTemp], heap[priorChildIndexTemp])) return;//比孩子結點優先,篩選結束
            else {
                //交換操做
                int temp = heap[rootIndexTemp];
                heap[rootIndexTemp] = heap[priorChildIndexTemp];
                heap[priorChildIndexTemp] = temp;
                rootIndexTemp = priorChildIndexTemp;//指針向下走,直到指定的last範圍內的葉節點爲止
            }
        }
    }
    
    
    /**
     * 看是大頂堆仍是小頂堆,決定是大於優先仍是小於優先
     * @param a
     * @param b
     * @return
     */
    private boolean prior(int a, int b) {
        if(heapType == 0)return a >= b;
        else return a <= b;
    }
    
    public static void main(String[] args) {
        int[] a = {0,3,6,1,8,12,55};//注意0號元素不用
        HeapSort heapSort = new HeapSort(0);//大頂堆,按正序排列
        heapSort.heapSort(a);
        show(a);
    }
    
    public static void show(int[] array) {
        for(int i= 1; i < array.length; i ++) {
            System.out.print(array[i] + "\t");
        }
        System.out.println();
    }
    
    /**
     * 插入後調整堆的算法
     * @param heap 
     * @param newEleIndex 新元素的序號
     */
    public void adjustHeapAfterInsert(int[] heap, int newEleIndex) {
        int indexTemp = newEleIndex;
        while(indexTemp > 1 && prior(heap[indexTemp], heap[indexTemp / 2])) {//還沒到根節點&&比雙親結點的優先級大——就要交換和指針上移
            int temp = heap[indexTemp];
            heap[indexTemp] = heap[indexTemp / 2];
            heap[indexTemp / 2] = temp;
            indexTemp = indexTemp / 2;
        }
    }
    
    
}
相關文章
相關標籤/搜索