1. 程式人生 > >堆排序HeapSort

堆排序HeapSort

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+2
5 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