堆排序

堆排序是利用堆這種數據結構而設計的一種排序算法,堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均爲O(nlogn),它也是不穩定排序。首先簡單瞭解下堆結構。
堆是具有以下性質的完全二叉樹:每個結點的值都大於或等於其左右孩子結點的值,稱爲大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱爲小頂堆。如下圖:
  在這裏插入圖片描述
同時,我們對堆中的結點按層進行編號,將這種邏輯結構映射到數組中就是下面這個樣子
在這裏插入圖片描述
該數組從邏輯上講就是一個堆結構,我們用簡單的公式來描述一下堆的定義就是:

大頂堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小頂堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

堆排序基本思想及步驟

堆排序的基本思想是:將待排序序列構造成一個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就爲最大值。然後將剩餘n-1個元素重新構造成一個堆,這樣會得到n個元素的次小值。如此反覆執行,便能得到一個有序序列了。

示例代碼:

package Sort;

import java.util.Arrays;

/**
 * @Auther: wj
 * @Date: 2020/2/6
 * @Description: 最大堆排序
 * @version: 1.0
 */
public class HeapSort {

    public static void main(String[] args){
        int[] arr={2,1,7,9,5,4};
        for(int i=0;i<arr.length;i++){
            maxHeapify(arr,arr.length-i);//arr.length-i 表示每次最大值存貯在數組最後一位
            //由於是最大堆排序,每次全數組排序後,最大值都在arr[0]
            int temp=arr[0];
            arr[0]=arr[arr.length-i-1];
            arr[arr.length-i-1]=temp;
        }
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 一次全數組的堆排序
     * @param arr 待排序數組
     * @param size 數組大小
     */
    public static void maxHeapify(int[] arr,int size){
        for(int i=size-1;i>=0;i--){
            Heapify(arr,i,size);
        }
    }

    /**
     * 堆排序(父與子之間)
     * @param arr 待排序數組
     * @param root 根節點
     * @param size 數組大小
     */
    public static void Heapify(int[] arr,int root,int size){
        int left=2*root+1;//左孩子
        int right=2*root+2;//右孩子
        int max=root;//假設最大值爲根節點

        if(left<size){
            if(arr[left]>=arr[max]){
                max=left;
            }
        }

        if(right<size){
            if(arr[right]>=arr[max]){
                max=right;
            }
        }
        //最大值不是根元素,就交換
        if(root!=max){
            int temp=arr[root];
            arr[root]=arr[max];
            arr[max]=temp;
        }
        //葉子節點,直接返回上一層
        if(root==max) return;
        //當前父子節點比較完成,繼續比較
        Heapify(arr, max, size);

    }

















   /* public static void main(String[] args) {
        int[] arr={2,1,8,9,5,4};
        //每次徹底堆排序後,最大元素在前,排除一個元素size-1
        for(int i=0;i<arr.length;i++){
            maxHeapify(arr,arr.length-i);
            //徹底一次排序後,最大值arr[0]與最後元素進行交換
            int temp=arr[0];
            arr[0]=arr[(arr.length-1)-i];
            arr[(arr.length-1)-i]=temp;
        }
        System.out.println(Arrays.toString(arr));
    }

    *//**
     * 一次徹底的堆排序,可以找出當前數組最大值
     * @param arr 排序數組
     * @param size 需要排序數組大小
     *//*
    public static void maxHeapify(int[] arr,int size){
        for(int i=size-1;i>=0;i--){
            heapify(arr,i,size);
        }
    }

    *//**
     * 堆排序(一次父與子)
     * @param arr 排序數組
     * @param root 當前父節點
     * @param size 數組大小(判斷是否還存在子節點)
     *//*
    public static void heapify(int[] arr,int root,int size){
        //如果當前父節點存在
        if(root<size){
            int left=2*root+1;//左孩子
            int right=2*root+2;//右孩子
            //默認當前節點爲最大值
            int max=root;

            if(left<size){
                if(arr[left]>=arr[max]){
                    max=left;
                }
            }

            if(right<size){
                if(arr[right]>=arr[max]){
                    max=right;
                }
            }

            //最大值不是根元素,就交換
            if(max!=root){
                int temp=arr[root];
                arr[root]=arr[max];
                arr[max]=temp;
            }

            // 只存在當前節點。沒有葉子節點存在-->結束遞歸條件
            if(max==root) return;

            //當前父子節點比較完成,完成下一次比較
            heapify(arr, max, size);
        }

    }*/
}

參考思路:堆排序

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