Java堆的實現和堆排序

public class Heap {

    private int[] a; // 數組,從下標1開始存儲數據
    private int n;  // 堆可以存儲的最大數據個數
    private int count; // 堆中已經存儲的數據個數

    public Heap(int capacity) {
        a = new int[capacity + 1];
        n = capacity;
        count = 0;
    }

    public void insert(int data) {
        if (count >= n) return; // 堆滿了
        ++count;
        a[count] = data;
        int i = count;
        while (i/2 > 0 && a[i] > a[i/2]) { // 自下往上堆化
            swap(a, i, i/2); // swap()函數作用:交換下標爲i和i/2的兩個元素
            i = i/2;
        }
    }


    public void removeMax() {
        // 堆中沒有數據
        if (count == 0) return;
        a[1] = a[count];
        --count;
        heapify(a, count, 1);
    }

    private static void heapify(int[] a, int n, int i) {
        while (true) {
            int maxPos = i;
            if (i*2 <= n && a[i] < a[i*2]) maxPos = i*2;
            if (i*2+1 <= n && a[maxPos] < a[i*2+1]) maxPos = i*2+1;
            if (maxPos == i) break;
            swap(a, i, maxPos);
            i = maxPos;
        }
    }


    private static void swap(int[] a, int p, int r) {
        int tmp = a[p];
        a[p] = a[r];
        a[r] = tmp;
    }
}

下面的是堆排序

/**
 * 堆排序
 */
public class HeapSort {

    /**
     * 排序
     * <p>
     * 堆元素是從數組下標0開始
     *
     * @param arr
     */
    public static void sort(int[] arr) {
        if (arr.length <= 1) {
            return;
        }

        // 1、建堆
        buildHeap(arr);

        // 2、排序
        int k = arr.length - 1;
        while (k > 0) {
            // 將堆頂元素(最大)與最後一個元素交換位置
            swap(arr, 0, k);
            // 將剩下元素重新堆化,堆頂元素變成最大元素
            heapify(arr, --k, 0);
        }
    }

    /**
     * 建堆
     *
     * @param arr
     */
    private static void buildHeap(int[] arr) {
        // (arr.length - 1) / 2 爲最後一個葉子節點的父節點
        // 也就是最後一個非葉子節點,依次堆化直到根節點
        for (int i = (arr.length - 1) / 2; i >= 0; i--) {
            heapify(arr, arr.length - 1, i);
        }
    }

    /**
     * 堆化
     *
     * @param arr 要堆化的數組
     * @param n   最後堆元素下標
     * @param i   要堆化的元素下標
     */
    private static void heapify(int[] arr, int n, int i) {
        while (true) {
            // 最大值位置
            int maxPos = i;
            // 與左子節點(i * 2 + 1)比較,獲取最大值位置
            if (i * 2 + 1 <= n && arr[i] < arr[i * 2 + 1]) {
                maxPos = i * 2 + 1;
            }
            // 最大值與右子節點(i * 2 + 2)比較,獲取最大值位置
            if (i * 2 + 2 <= n && arr[maxPos] < arr[i * 2 + 2]) {
                maxPos = i * 2 + 2;
            }
            // 最大值是當前位置結束循環
            if (maxPos == i) {
                break;
            }
            // 與子節點交換位置
            swap(arr, i, maxPos);
            // 以交換後子節點位置接着往下查找
            i = maxPos;
        }
    }

    private static void swap(int []arr,int a,int b){
        if (a==b)return;
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }


    public static void main(String[] args) {
        int [] a = {2,2,1,2,4,5,1,6,9};
        sort(a);
        System.out.println(Arrays.toString(a));
    }


}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章