堆排序HeapSort
阿新 • • 發佈:2017-10-09
boolean i++ ref ++ iss pub heapsort style 函數
學習參考:堆排序 Heap Sort、排序六 堆排序
堆結構:一棵完全二叉樹。大根堆:K[ i ] < K[ 2i ] 、K[ i ] < K[ 2i+1 ] 。小根堆反之。
本文測試數據:《嚴奶奶數據結構》P281
由於筆者學業繁忙,沒有編寫使樹形結構可視化的代碼。各位讀者請心中腦補。
- 堆調整函數:
1 protected void HeapAdjust(int [] nums,int a,int b){ 2 int i; 3 for(i=a;a<=b;){ 4 //左子樹=根*2+1,右子樹=根*2+25 int lPos=a*2+1; 6 int rPos=(a+1)*2; 7 //比較找出左右子樹最小的一顆 8 int min=nums[a];//根結點 9 int nextPos=lPos;//下一個轉向的樹 10 boolean isSwaped=false; 11 if(lPos<=b && nums[lPos]<min){ 12 nextPos=lPos;13 min=nums[lPos]; 14 isSwaped=true; 15 } 16 if(rPos<=b && nums[rPos]<min){ 17 nextPos=rPos; 18 isSwaped=true; 19 } 20 if(!isSwaped) break; 21 swap(nums,a,nextPos);22 a=nextPos; 23 } 24 }
函數描述:這個函數用於【建堆】、【篩選】兩個操作。在這個函數中,對數組【a,b】中的元素進行處理,其認為除了“a”,在【a+1,b】中的元素都是滿足{堆結構}的定義的。
1.求出左右子樹的下標 2.進行比較,在左右子樹存在的情況下,獲得值最小的子樹(這個值最小的子樹,它的值要比根節點的值小) 3.如果沒有這樣的子樹,跳出循環。 有的話,轉到子樹進行操作,回到 1 進行循環。
- 建堆
1 //建堆 2 for(i=len/2-1;i>=0;i--){ 3 HeapAdjust(nums,i,len-1); 4 }
認為最下層的子樹是規整(滿足堆定義)的。通過從下層往上層調整,建立一棵滿足堆定義的小根堆。
- 篩選
1 //篩選 2 int ans[]=new int [len]; 3 for(i=0;i<len;i++){ 4 ans[i]=nums[0]; 5 nums[0]=nums[len-1-i]; 6 HeapAdjust(nums,0,len-2-i); 7 }
1.拿出小根堆的根節點(最小),放入輸出數組中
2.把最末尾的節點放入根節點。因為認為現在除了根節點,其他節點都是滿足根定義的。所以對根節點使用【堆調整函數】
3.重復 1,直到拿走堆中所有的節點。
測試:
輸入:49,38,65,97,76,13,27,49
輸出:13 27 38 49 49 65 76 97
完整java代碼:
1 public class Main { 2 3 public static void main(String[] args) { 4 int []nums={49,38,65,97,76,13,27,49}; 5 HeapSort sort=new HeapSort(nums); 6 System.out.print(sort); 7 } 8 9 } 10 11 class HeapSort{ 12 int [] sortAns; 13 HeapSort(){} 14 HeapSort(int[] nums){ 15 int i; 16 int len=nums.length; 17 //建堆 18 for(i=len/2-1;i>=0;i--){ 19 HeapAdjust(nums,i,len-1); 20 } 21 //篩選 22 int ans[]=new int [len]; 23 for(i=0;i<len;i++){ 24 ans[i]=nums[0]; 25 nums[0]=nums[len-1-i]; 26 HeapAdjust(nums,0,len-2-i); 27 } 28 sortAns=ans; 29 } 30 //對[a,b]的元素進行調整。認為除了a都滿足堆的條件 31 protected void HeapAdjust(int [] nums,int a,int b){ 32 int i; 33 for(i=a;a<=b;){ 34 //左子樹=根*2+1,右子樹=根*2+2 35 // System.out.println("a="+a); 36 int lPos=a*2+1; 37 int rPos=(a+1)*2; 38 //比較找出左右子樹最小的一顆 39 int min=nums[a];//根結點 40 int nextPos=lPos;//下一個轉向的樹 41 boolean isSwaped=false; 42 if(lPos<=b && nums[lPos]<min){ 43 nextPos=lPos; 44 min=nums[lPos]; 45 isSwaped=true; 46 } 47 if(rPos<=b && nums[rPos]<min){ 48 nextPos=rPos; 49 isSwaped=true; 50 } 51 if(!isSwaped) break; 52 swap(nums,a,nextPos); 53 a=nextPos; 54 } 55 } 56 void printNums(int[] nums){ 57 int i; 58 for(i=0;i<nums.length;i++) System.out.print(nums[i]+" "); 59 System.out.println(); 60 } 61 private void swap(int []arr,int a,int b){ 62 int tmp=arr[a]; 63 arr[a]=arr[b]; 64 arr[b]=tmp; 65 } 66 public String toString(){ 67 int i; 68 String str=new String(""); 69 for(i=0;i<sortAns.length;i++) str+=String.valueOf(sortAns[i])+" "; 70 str+="\n"; 71 return str; 72 } 73 }
堆排序HeapSort