1. 程式人生 > 其它 >完全二叉樹之堆

完全二叉樹之堆

  • 用堆降序排序
     1 //
     2 #include <stdio.h>
     3 
     4 int h[101]; //用來存放堆的陣列
     5 int n; //用來儲存堆中元素的個數,也就是堆的大小
     6 
     7 //建立堆
     8 void creat() {
     9     int i;
    10     //從最後一個非葉節點到第1個結點依次進行向上調整
    11     for (i = n / 2; i >= 1; i--) {
    12         siftdown(i);
    13     }
    14 }
    15 
    16 //刪除最大的元素
    17 int deletemax() {
    18     int t;
    
    19 t = h[1]; //用一個臨時變數記錄堆頂點的值 20 h[1] = h[n]; //將堆的最後一個點賦值到堆頂 21 n--; //堆的元素減少1 22 siftdown(1); //向下調整 23 return t; //返回之前記錄的堆的頂點的最大值 24 } 25 26 //向下調整 27 void siftdown(int i) { //傳入一個需要向下調整的結點編號i,這裡傳入1,即從堆的頂點開始開始向下調整 28 int t, flag = 0; //flag用來標記是否需要繼續向下調整 29 //當i結點有兒子(其實是至少有左兒子)且需要繼續調整時,迴圈
    30 while (i * 2 <= n && flag == 0) { 31 //首先判斷它和左兒子的關係,並用t記錄較小的結點編號 32 if (h[i] > h[i * 2]) 33 t = i * 2; 34 else 35 t = i; 36 //如果它有右兒子,再對右兒子進行討論 37 if (i * 2 + 1 <= n) { 38 //如果右兒子的值更小,更新較小的結點編號 39 if
    (h[t] > h[i * 2 + 1]) 40 t = i * 2 + 1; 41 } 42 //如果發現最小的結點編號不是自己,說明子結點中有比父結點更小的 43 if (t != 1) { 44 swap(t, i); //交換它們 45 i = t; //更新i為剛才與它交換的二子結點的編號,便於接下來繼續向下調整 46 } else 47 flag = 1; //否則說明當前的父結點已經比兩個子結點都小,不需要進行調整 48 } 49 } 50 51 //交換函式,用來交換堆中的兩個元素的值 52 void swap(int x, int y) { 53 int t; 54 t = h[x]; 55 h[x] = y; 56 y = t; 57 } 58 59 int main() { 60 int i, j, num; 61 //讀入要排序的數字的個數 62 scanf("%d", &num); 63 64 for (i = 1; i <= num; i++) 65 scanf("%d", &h[i]); 66 n = num; 67 68 //建堆 69 creat(); 70 71 //刪除頂部元素,連續刪除n次,其實也就是從大到小把數輸出出來 72 for (i = 1; i <= num; i++) 73 printf("%d ", deletemax()); 74 75 return 0; 76 }