排序演算法 - 堆排序

b9x_發表於2018-03-11

堆排序時利用堆進行排序的。
堆:具有以下性質的完全二叉樹:每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆。堆左右孩子之間的大小沒有要求。
堆排序的基本思想是:將待排序序列構造成一個大頂堆(小頂堆),此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然後將剩餘n-1個元素重新構造成一個堆,這樣會得到n個元素的次小值。

package com.zx.sort;

import java.util.Arrays;

public class Heap {
       public static void main(String []args){
            int []arr = {5,3,69,132,5,65,13,4};
            sort(arr);
            System.out.println(Arrays.toString(arr));
        }
        public static void sort(int []arr){
            for(int i=arr.length/2-1;i>=0;i--){
                //從最後一個非葉子節點開始從下往上,從右至左調整堆結構
                adjustHeap(arr,i,arr.length);
            }
            for(int j=arr.length-1;j>0;j--){
                //將堆頂元素與末尾元素進行交換
                int temp=arr[0];
                arr[0] = arr[j];
                arr[j] = temp;
                adjustHeap(arr,0,j);//重新對堆進行調整
            }
        }

        public static void adjustHeap(int []arr,int i,int length){
            int temp = arr[i];
            for(int k=i*2+1;k<length;k=k*2+1){//從i結點的左子結點開始,也就是2i+1處開始
                if(k+1<length && arr[k]<arr[k+1]){//如果左子結點小於右子結點,k指向右子結點
                    k++;
                }
                if(arr[k] >temp){//將子節點值賦給父節點(不用進行交換,因為最後temp會放置到最終的位置(i處),就是i與最大的直接交換下)
                    arr[i] = arr[k];
                    i = k;
                }else{
                    break;
                }
            }
            arr[i] = temp;//將temp值放到最終的位置
        }


}

堆排序最壞,最好,平均時間複雜度均為O(nlogn),它是不穩定的排序。

相關文章