天天看點

一步一步解析java排序算法--堆排序(最小堆)

首先明确什麼是堆?

一個數組:

int[] unsort={12,24,35,40,50,66,70,56,55};

堆的表現形式(這是一個最小堆,根節點是最小的):

一步一步解析java排序算法--堆排序(最小堆)

用數組來表示堆,i結點的父結點下标就為(i – 1) / 2。它的左右子結點下标分别為2 * i + 1和2 * i + 2。(這樣就是給數組建好堆了)

下面進入堆排序的核心步驟:堆節點的移動

一步一步解析java排序算法--堆排序(最小堆)

這裡需要對unsort[3]=12進行調整

一步一步解析java排序算法--堆排序(最小堆)

對unsort[3]的子節點unsort[7],unsort[8]進行比較,符合最小堆!

對unsort[1]=24進行調整

一步一步解析java排序算法--堆排序(最小堆)

跟左子節點進行調整

對unsort[0]=40進行調整

一步一步解析java排序算法--堆排序(最小堆)

比較左右子節點,12<35;

12<40進行調整,上移;

比較左右子節點,24<50;

24<40,上移;

55<56;55>40;至此調整結束,24所在索引位置替換成40;

最小堆的根節點值最小。

下面看代碼:

//從i節點開始調整, i節點的子節點為 2*i+1, 2*i+2
        public static void MinHeapFixdown(int a[], int i, int n)  
        {  
            int j, temp;  

            temp = a[i]; //取出節點值,比較,替換 
            j =  * i + ;  //左子節點
            while (j < n)  
            {  
                if (j +  < n && a[j + ] < a[j]) //在左右子節點中找最小的  
                    j++;  

                if (a[j] >= temp)  //說明已經排好序
                    break;  

                a[i] = a[j];     //把較小的子結點往上移動,替換它的父結點  
                i = j;  
                j =  * i + ;  //繼續往下周遊比較
            }  
            a[i] = temp; //調整結束 
        }    
           

有了堆的調整操作,建立堆,進行堆排序:

/**
         * 建立最小堆  
         * 對數組中的每個元素進行子節點調整,最小的向上移動
         * @param a 數組
         * @param n 數組長度
         */
        static void MakeMinHeap(int a[], int n)  
        {  
            //n/2-1可以定位到最後一個數組元素了,子節點分别為n-2,n-1
            for (int i = n /  - ; i >= ; i--)  
                MinHeapFixdown(a, i, n);  
        }  
        public static void MinheapsortTodescendarray(int a[], int n)  
        {  
            for (int i = n ; i >= ; i--)  
            {  
                MakeMinHeap(a,i);//從根節點調整定位最小值,調整過後a[0]最小 
                swap(a,i-,);//交換值,此時a[0]最小,進行下沉;下次周遊進行調整不會調整a[i-1]
            }  
        }  
           

此時得到的數組是遞減的:

public static void main(String[] args) {
        int[] unsort={,,,,,,,,};
        MinheapsortTodescendarray(unsort, unsort.length);
        for (int i = ; i < unsort.length; i++) {
            System.out.print("  "+unsort[i]);
        }

    }
           

運作結果:

101 100 80 56 55 40 24 12 8