堆排序是一種利用完全二叉樹來解決問題的高效算法,合法的最大堆樹要滿足一個條件就是每一個結點值都要大於或等於它的孩子結點值。在一個數組中那專業法表示為:
arrays[i]>=arrays[2*i+1] && arrays[i]>=arrays[2*i+2]; 最小堆類似,只要改為冒最小值即可。
堆排序樹的構造過程找最大值過程由下圖,數組arrays[0....n]為:17,8,45,84,2,94,剛找到最大值后把最大值即94放在數組的最后面arrays[n],
然后進入遞歸把arrays[0...n-1]再進入下面圖這個過程,只是把排好序的最大值不放入到這個過程中,就這樣把值一個個的冒出來。
,找到最大值后把這個最大值放到數組的最后面,進入下一個遞歸。
上圖已經排好了最大那個值 下面見圖排其他的元素:
最后兩步還有幾個過程沒畫出來,最后兩個圖好像沒有變化,但這里面還要排好幾次,原因就是最后第二個圖是不滿足堆排序樹的要調整后再把最大的值放到到后面。再次回到遞歸里面。
全代碼實現由下:
public class Heap { public void heap_sort(int[] arrays,int e){ if(e>0){ init_sort(arrays,e);//初始化堆,找出最大的放在堆頂 // snp(arrays); arrays[0]=arrays[e]+arrays[0]; arrays[e]=arrays[0]-arrays[e]; arrays[0]=arrays[0]-arrays[e]; // snp(arrays); heap_sort(arrays, e-1); }else{ snp(arrays); } } public void snp(int[] arrays){ for(int i=0;i<arrays.length;i++){ System.out.print(arrays[i]+" "); } System.out.println(); } public void init_sort(int[] arrays,int e){ int m=(e+1)/2; for(int i=0;i<m;i++){ boolean flag=build_heap(arrays,e,i); //如果孩子之間有交換,就要重新開始 if(flag){ i=-1; } } } //返回一個標記,如果有根與孩子交換就要重新從頂根開始查找不滿足最大堆樹結構 public boolean build_heap(int arrays[],int e,int i){ int l_child=2*i+1;//左孩子 int r_child=2*i+2;//右孩子 if(r_child>e){ //判斷是否有右孩子,沒有的話直接比較,小於交換 if(arrays[i]<arrays[l_child]){ arrays[i]=arrays[i]+arrays[l_child]; arrays[l_child]=arrays[i]-arrays[l_child]; arrays[i]=arrays[i]-arrays[l_child]; return true; }else{ return false; } } //在根與兩個孩子之間找出最大的那個值進行交換 if(arrays[i]<arrays[l_child]){ if(arrays[l_child]>arrays[r_child]){ //交換根與左孩子的值 arrays[i]=arrays[i]+arrays[l_child]; arrays[l_child]=arrays[i]-arrays[l_child]; arrays[i]=arrays[i]-arrays[l_child]; return true; }else{ //交換根與右孩子的值 arrays[i]=arrays[i]+arrays[r_child]; arrays[r_child]=arrays[i]-arrays[r_child]; arrays[i]=arrays[i]-arrays[r_child]; return true; } }else if(arrays[i]<arrays[r_child]){ //交換根與右孩子的值 arrays[i]=arrays[i]+arrays[r_child]; arrays[r_child]=arrays[i]-arrays[r_child]; arrays[i]=arrays[i]-arrays[r_child]; return true; } return false; } public static void main(String[] args) { Heap h=new Heap(); int [] a={17,8,45,84,2,94}; h.heap_sort(a,a.length-1); } }
運行打印過程由下,這個結果可以對着上面的樹來看,容易理解:
---------- java ----------
94 45 84 8 2 17
17 45 84 8 2 94
84 45 17 8 2 94
2 45 17 8 84 94
45 8 17 2 84 94
2 8 17 45 84 94
17 8 2 45 84 94
2 8 17 45 84 94
8 2 17 45 84 94
2 8 17 45 84 94
輸出完成 (耗時 0 秒) - 正常終止