1.將待排序列以一個徹底二叉樹存儲,設二叉樹的深度爲h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第h層全部的結點都連續集中在最左邊,這就是徹底二叉樹。數組
2.第一趟排序,從二叉樹的最後一個根節點(有步驟1可知是值爲12的節點)開始,調整當前節點所在的堆,使當前節點大於全部子節點的值,最終獲得的堆是最大根堆。spa
(1)12->363d
(2)73->81code
(3)49->98對象
(4)55->81->73blog
(5)40->98->49排序
3.第二趟排序,每趟排序後,待排序列中的最大值將被移動到根節點,將根節點元素與待排序列中最後一個元素交換位置,紅色元素表示已經排好的序列,紅色元素不參與下輪的排序過程class
(1)98->12二叉樹
(2)12->81->73->64im
(3)81->12
(4)12->73->64->55
(5)73->12
(6)12->64->55
(7)64->40
(8)40->55
(9)55->27
(10)27->49
(11)49->36
(12)36->40
(13)40->12
(14)12->36
(15)36->27
(16)27->12
(16)12->12
代碼:
package com.zjl.tool.sort; /** * 堆排序 * @author huanongying * */ public class HeapSort { /** * @param args */ public static void main(String[] args) { int[] arr = {40,55,49,73,12,27,98,81,64,36};//待排序數組 HeapSort(arr, arr.length - 1);//將arr按照降序排列 //打印排序後的數組 for(int value : arr) { System.out.print(value + " "); } } /** * 待排序列(R1,R2,...,Rk,...Rn)看做是徹底二叉樹,經過比較、交換,父節點和孩子節點的值, * 使得對於任意元素Rk(k<=n/2),知足Rk>=R(2k),Rk>=R(2k+1) * @param arr 數組對象 * @param start 數組的開始下標 * @param end 數組的結束下標 */ private static void HeapAdjust(int[] arr, int start, int end) { //當下標爲start的元素有孩子元素時 while(start <= end/2) { //left和right分別爲左右孩子元素的下標,max爲左右孩子中值較大的孩子的元素下標 int left = 2 * start+1; int right = 2 * start+2; int max = 0; //若是既有左孩子,又有右孩子 if(left < end&&right <= end) { //若是左孩子小於右孩子的值,max = right,不然爲max = left if(arr[left] <= arr[right]) max = right; else max = left; } //若是隻有左孩子,沒有右孩子,max值爲left if(left <= end&&right > end) { max = left; } //若是沒有孩子,則代表到了徹底二叉樹的葉子節點 if(left > end) { break; } //若是當前節點值小於兩孩子中的值較大者,那麼將當前節點值與max交換 if(arr[start] < arr[max]){ int tmp = arr[start]; arr[start] = arr[max]; arr[max] = tmp; } //當前節點向孩子節點迭代 start = max; } } /** * @param arr 數組 * @param end 數組結束下標 */ private static void HeapSort(int[] arr, int end) { //由最後一個非葉子節點,向根節點迭代,建立最大堆,數組中的最大值將被移動到根節點 for(int start = end/2;start >= 0;start--) { HeapAdjust(arr, start, end); } while(end > 0){ //交換arr[0]和arr[end]的值 int tmp = arr[0]; arr[0] = arr[end]; arr[end] = tmp; //排序範圍變爲(0,end-1) HeapAdjust(arr, 0, end - 1); end--; } } }