堆排序--java實現

堆排序--java實現

一.堆排序

​ 堆排序(Heap Sort)是指利用堆這種數據結構所設計的一種排序算法。堆是一個近似徹底二叉樹的結構,並同時知足堆積的性質:即子結點的鍵值或索引老是小於(或者大於)它的父節點。java

2、堆

什麼是堆?
堆是一個樹形結構,其實堆的底層是一棵徹底二叉樹。而徹底二叉樹是一層一層按照進入的順序排成的。按照這個特性,咱們能夠用數組來按照徹底二叉樹實現堆。
普通堆大頂堆與小頂堆
大頂堆原理:根結點(亦稱爲堆頂)的關鍵字是堆裏全部結點關鍵字中最大者,稱爲大頂堆。大頂堆要求根節點的關鍵字既大於或等於左子樹的關鍵字值,又大於或等於右子樹的關鍵字值。
小頂堆原理:根結點(亦稱爲堆頂)的關鍵字是堆裏全部結點關鍵字中最小者,稱爲小頂堆。小堆堆要求根節點的關鍵字既小於或等於左子樹的關鍵字值,又小於或等於右子樹的關鍵字值。算法

大頂堆-小頂堆

3、推排序思想

  1. 構建初始堆,將待排序列構成一個大頂堆(或者小頂堆),升序大頂堆,降序小頂堆;
  2. 將堆頂元素與堆尾元素交換,並斷開(從待排序列中移除)堆尾元素。
  3. 從新構建堆。
  4. 重複2~3,直到待排序列中只剩下一個元素(堆頂元素)。

4、圖解

案例1堆排序動畫演示

五.代碼實現

public class HeapSort {

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<Integer>();

        for (int i = 0; i < 10; i++) {
            list.add((int) (Math.random() * 100));
        }
        System.out.println("排序前的集合爲:");
        System.out.println(Arrays.toString(list.toArray()));

        heapSort(list);

        System.out.println("排序後的集合爲:");
        System.out.println(Arrays.toString(list.toArray()));
    }

    /**
     * 建立堆,
     * @param list 待排序列
     */
    private static void heapSort(List<Integer> list) {
        //建立堆
        for (int i = (list.size() - 1) / 2; i >= 0; i--) {
            //從第一個非葉子結點從下至上,從右至左調整結構
            adjustHeap(list, i, list.size());
        }

        System.out.println("dadui的集合爲:");
        System.out.println(Arrays.toString(list.toArray()));

        //調整堆結構+交換堆頂元素與末尾元素
        for (int i = list.size() - 1; i > 0; i--) {
            //將堆頂元素與末尾元素進行交換
            int temp = list.get(i);
            list.set(i, list.get(0));
            list.set(0, temp);

            //從新對堆進行調整
            adjustHeap(list, 0, i);
        }
    }

    /**
     * 調整堆
     * @param list 待排序列
     * @param parent 父節點
     * @param length 待排序列尾元素索引
     */
    private static void adjustHeap(List<Integer> list, int parent, int length) {
        //將temp做爲父節點
        int temp = list.get(parent);
        //左孩子
        int lChild = 2 * parent + 1;

        while (lChild < length) {
            //右孩子
            int rChild = lChild + 1;
            // 若是有右孩子結點,而且右孩子結點的值大於左孩子結點,則選取右孩子結點
            if (rChild < length && list.get(lChild) < list.get(rChild)) {
                lChild++;
            }

            // 若是父結點的值已經大於孩子結點的值,則直接結束
            if (temp >= list.get(lChild)) {
                break;
            }

            // 把孩子結點的值賦給父結點
            list.set(parent, list.get(lChild));

            //選取孩子結點的左孩子結點,繼續向下篩選
            parent = lChild;
            lChild = 2 * lChild + 1;
        }
        list.set(parent, temp);
    }

}
相關文章
相關標籤/搜索