堆排序

堆排序

1 什麼是堆
堆的定義

在這裏插入圖片描述
在這裏插入圖片描述
把這個關係 和完全二叉樹對應起來,如下圖,如果 下標 從1 開始, 這 任意一個節點 i 2i +1 2i +2
對於小標從 i ==1 下標從0開始i ==0 的情況
在這裏插入圖片描述

來看下 下面 是 不是堆 ?
在這裏插入圖片描述
左面 是 小頂堆 ; 右面是 大頂堆

看看下面的圖形
在這裏插入圖片描述

左邊 3 6 7 不滿足 大頂堆的定義, 中間 大頂堆 右面 是 大頂堆

2 堆的存儲的結構
在這裏插入圖片描述
圖1 爲 實際 存儲結構 , 圖2 右面 放在 完全二叉樹中的邏輯結構。
3 如何建立 大頂堆
用上面的結構爲例 進行圖解

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

此時建立 了 大頂堆, 將 第0 個元素的 待排序列中的最後一個位置互換位置。 之後對 0 —> 12 進行 最大堆調整 即可,
直到i==0 時候, 待排 序列 就全部完成, 此時 arr[] 排成的 升序啦。。
在這裏插入圖片描述

4 開始 調整堆

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
5 堆排序的過程

堆排序的過程是:
(1)建立一個堆array[0…n-1]。
(2)把堆首(最大值)和堆尾互換。
(3)把堆的尺寸縮小1,然後調整堆,目的構成新的堆。
(4)重複步驟2,直到堆的尺寸爲1,排序完成。

#include <stdio.h>  
 
/* 交換元素 */  
void  swap (int array[], int i, int j){
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}
 
void  printAaray(int array[] ,int len){
       for(int i=0; i < len; i++){
         printf("%d  ", array[i]);
 
        }
       printf("\n");
}
 
 
/* 調整堆 */  
void heap_ajust(int arr[], int start, int end) {  
    //建立父節點下標和子節點下標  
    int dad = start;  
    int son = dad * 2 + 1;  
    while (son <= end) { //   
        if (son + 1 <= end && arr[son] < arr[son + 1]) //先比較兩個子節點大小,選擇最大的  
            son++;  
        if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數  
            return;  
        else { //否則交換父子內容再繼續子節點和孫節點比較  
            swap(arr,dad,son);  
            dad = son;  
            son = dad * 2 + 1;  
        }  
    }  
}  
  
 
/* 堆排序 */  
void heap_sort(int arr[], int len) {  
    int i;  
    //初始化堆,i從最後一個父節點開始調整  
    // 建立最大堆 
    for (i = len / 2 - 1; i >= 0; i--) {
        heap_ajust(arr, i, len - 1);  
 
    }       
    //先將第一個元素和已排好元素前一位做交換,再從新調整,直到排序完畢  
    for (i = len - 1; i > 0; --i) {  
        
        swap(arr,0,i);
        heap_ajust(arr, 0, i-1);  
    }  
}  
  
int main(int argc, char const *argv[]) {  
 
    int arr[]={1,34,6,21,98,31,7,4,36,47,39,45,5,2};
    int length = sizeof(arr) / sizeof(int);  
    /* sort */  
    heap_sort(arr, length);  
      
    /* print Array */   
    printAaray(arr,length);
  
    return 0;  
}  

同理 一直這樣調整 堆 把調整成 大頂堆, 之後將堆頂的元素和待排序列的最後的一個元素 互換值,之後 帶排序序列減1 , 已排序列 加1 。
最後 i ==0 ,此時就剩一個 待排序列 ,也就完成了所有的排序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章