1. 程式人生 > >排序演算法(九)——堆排序

排序演算法(九)——堆排序

堆排序(Heap Sort)演算法是基於選擇排序思想的演算法,其利用堆結構和二叉樹的一些性質來完成資料的排序。

堆排序演算法的運作如下:

(1)將陣列變為一個大頂堆。

(2)因為大頂堆的根結點為陣列中的最大值,然後每次把根結點放到陣列的最後面,並固定住。

(3)以此類推,將前面的數字變為一個大頂堆...

package cn.kimtian.sort;

import java.util.Arrays;

/**
 * 堆排序
 *
 * @author kimtian
 */
public class HeapSort {
    public static void main(String[] args) {
        int[] arr = new int[]{9, 6, 8, 7, 0, 1, 10, 4, 2};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 堆排序演算法
     *
     * @param arr
     */
    public static void heapSort(int[] arr) {
        //從開始位置喀什調整,開始位置為最後一個非葉子結點,即最後一個結點的父結點
        int start = (arr.length - 1) / 2;
        //結束位置為陣列的長度-1,迴圈調整陣列為一個大頂堆
        for (int i = start; i >= 0; i--) {
            maxHeap(arr, arr.length, i);
        }
        //調整成大頂堆之後我們把陣列的第一個值挪到最後面,並固定住。
        //再把前面的處理為大頂堆
        for (int i = arr.length - 1; i >= 0; i--) {
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            maxHeap(arr, i, 0);
        }
    }

    /**
     * 先將一個數組變為大頂堆的方法
     * 任意一個數組都可以變成一個完全二叉樹,再將二叉樹變為大頂堆
     * (1)從最後一個非葉子結點開始調整,拿著這個結點和子結點對比,如果不是最大的,則交換位置。
     * (2)再處理下一個非葉子結點。以此類推。
     *
     * @param arr   調整的陣列
     * @param size  調整陣列的哪裡一部分
     * @param index 從陣列的哪開始調整
     */
    public static void maxHeap(int[] arr, int size, int index) {
        //從index找到兩個子結點
        int leftNode = 2 * index + 1;
        int rightNode = 2 * index + 2;
        int max = index;
        //和兩個子結點分別對比,找出最大的結點
        if (leftNode < size && arr[leftNode] > arr[max]) {
            max = leftNode;
        }
        if (rightNode < size && arr[rightNode] > arr[max]) {
            max = rightNode;
        }
        //根據最大值來進行交換位置
        if (max != index) {
            int temp = arr[index];
            arr[index] = arr[max];
            arr[max] = temp;
            //交換位置後,可能會破壞之前排好的堆,所以,之前排好的堆需要重新調整
            maxHeap(arr, size, max);
        }


    }

}