堆排序原理 C語言實現(xiàn)堆排序及過程詳解

堆排序就是把最大堆堆頂?shù)淖畲髷?shù)取出毒坛,將剩余的堆繼續(xù)調整為最大堆,再次將堆頂?shù)淖畲髷?shù)取出(最大堆調整的遞歸運算),這個過程持續(xù)到剩余數(shù)只有一個時結束辨泳。在堆中定義以下幾種操作:

最大堆調整(Max-Heapify):

將堆的末端子節(jié)點作調整,使得子節(jié)點永遠小于父節(jié)點

創(chuàng)建最大堆(Build-Max-Heap):

將堆所有數(shù)據重新排序玖院,使其成為最大堆

堆排序(Heap-Sort):

移除位在第一個數(shù)據的根節(jié)點菠红,并做最大堆調整的遞歸運算

繼續(xù)進行下面的討論前,需要注意的一個問題是:數(shù)組都是 Zero-Based难菌,這就意味著我們的堆數(shù)據結構模型要發(fā)生改變


heap-and-array-zero-based.png

相應的试溯,幾個計算公式也要作出相應調整:
Parent(i) = floor((i-1)/2),i 的父節(jié)點下標
Left(i) = 2i + 1郊酒,i 的左子節(jié)點下標
Right(i) = 2(i + 1)遇绞,i 的右子節(jié)點下標
最大堆調整(MAX‐HEAPIFY)的作用是保持最大堆的性質,是創(chuàng)建最大堆的核心子程序燎窘,作用過程如圖所示:


max‐heapify-procedure.png

創(chuàng)建最大堆(Build-Max-Heap)的作用是將一個數(shù)組改造成一個最大堆摹闽,接受數(shù)組和堆大小兩個參數(shù),Build-Max-Heap 將自下而上的調用 Max-Heapify 來改造數(shù)組褐健,建立最大堆付鹿。因為 Max-Heapify 能夠保證下標 i 的結點之后結點都滿足最大堆的性質,所以自下而上的調用 Max-Heapify 能夠在改造過程中保持這一性質蚜迅。如果最大堆的數(shù)量元素是 n舵匾,那么 Build-Max-Heap 從 Parent(n) 開始,往上依次調用 Max-Heapify慢叨。流程如下
building-a-heap.png

堆排序(Heap-Sort)是堆排序的接口算法纽匙,Heap-Sort先調用Build-Max-Heap將數(shù)組改造為最大堆,然后將堆頂和堆底元素交換拍谐,之后將底部上升烛缔,最后重新調用Max-Heapify保持最大堆性質馏段。由于堆頂元素必然是堆中最大的元素,所以一次操作之后践瓷,堆中存在的最大元素被分離出堆院喜,重復n-1次之后,數(shù)組排列完畢晕翠。整個流程如下:


HeapSort.png

C語言實現(xiàn):

#include <stdio.h>
#include <stdlib.h>

void swap(int *arr,int i, int k) 
{
    int temp = arr[i];
    arr[i] = arr[k];
    arr[k] = temp;
}


void max_heapify(int *arr, int start, int end) 
{
    //建立父節(jié)點下標和子節(jié)點下標
    int dad = start;

    int son = dad * 2 + 1;

    while (son <= end) 
    {   //若子節(jié)點下標在范圍內才做比較
        if (son + 1 <= end && arr[son] < arr[son + 1]) //先比較兩個子節(jié)點大小喷舀,選擇最大的
        {
            son++;
        
        }

        if (arr[dad] > arr[son]) //如果父節(jié)點大于子節(jié)點代表調整完畢,直接跳出
        {
            return;
        }   
        else 
        {   //否則交換父子節(jié)點的值再繼續(xù)左右子節(jié)點值得比較
            swap(arr,dad, son);
            printf("dad=%d--son=%d\n",dad,son);
            dad = son;
            son = dad * 2 + 1;
        }
            
    }
}

void heap_sort(int *arr, int len) 
{
    int i;
    //初始化,i從最后一個父節(jié)點開始調整
    for (i = len / 2 - 1; i >= 0; i--)
    {
        max_heapify(arr, i, len - 1);
        
    }


    for (i = len - 1; i > 0; i--) 
    {
        swap(arr,0, i);

        max_heapify(arr, 0, i - 1);
    }
}

int main(int argc, char const *argv[])
{
    int arr[] = {5,3,8,1,6};

    int len = sizeof(arr) / sizeof(int);

    heap_sort(arr, len);

    for (int i = 0; i < len; i++)
    {
        printf("%d ", arr[i]);
    }
        
    printf("\n");
    
    return 0;
}

步驟詳解:
下標0 1 2 3 4

數(shù)組5 3 8 1 6
001.png

Array={5,3,8,1,6};
Len=5
i=5/2 -1 =1 為最后一個元素的父節(jié)點的下標值
Max_heapity(arr,i,len-1)
i=1 len-1=4 end=4
1 > 6 son=4

第一次交換3和6值
002.png

dad=4
son=4*2+1=9
9>4 while 第一次結束

i=0
Max_heapity(arr,0,4)

dad=0 ; end=4 son=1
1 < 4
6< 8
son=2

第二次 交換5和8值(此時為最大堆)
003.png

dad=2
son=2*2 +1 =5
5<end=4 while 第二次結束

i=-1 i<0 第一個for循環(huán)結束

第二個for循環(huán)開始
len=5
i=len-1=4

swap(arr,0,4)
004.png

max_heapity(arr,0,3)
dad=0 son=1 end=3

swap(arr,0,1)
005.png

son=3 dad=1
while 第三次結束

i=3 len=5

swap(arr,0,3)
006.png

max_heapify(arr,0,2);
dad=0; son=1;end=2
3 < 5
son=2

swap(arr,0,2);
007.png

dad=2
son=2*2+1=5

while 第四次結束

i=2 len=5

swap(arr,0,2)
008.png

max_heapity(arr,0,1)

dad=0; son=1 end=1

swap(arr,0,1);
009.png

i=1 len=5
max_heapity(arr,0,0)

dad=0; son =1
1<0 while跳出

最后堆頂?shù)淖畲髷?shù)3取出 再取出1
010.png

i=0時 第二個for循序結束
最終結果: 13 5 6 8

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末淋肾,一起剝皮案震驚了整個濱河市硫麻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌樊卓,老刑警劉巖拿愧,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異碌尔,居然都是意外死亡浇辜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門唾戚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柳洋,“玉大人,你說我怎么就攤上這事叹坦⌒芰停” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵立由,是天一觀的道長轧钓。 經常有香客問我,道長锐膜,這世上最難降的妖魔是什么毕箍? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮道盏,結果婚禮上而柑,老公的妹妹穿的比我還像新娘。我一直安慰自己荷逞,他們只是感情好媒咳,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著种远,像睡著了一般涩澡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坠敷,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天妙同,我揣著相機與錄音射富,去河邊找鬼。 笑死粥帚,一個胖子當著我的面吹牛胰耗,可吹牛的內容都是我干的。 我是一名探鬼主播芒涡,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼柴灯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了费尽?” 一聲冷哼從身側響起赠群,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旱幼,沒想到半個月后乎串,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡速警,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸯两。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闷旧。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖钧唐,靈堂內的尸體忽然破棺而出忙灼,到底是詐尸還是另有隱情,我是刑警寧澤钝侠,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布该园,位于F島的核電站,受9級特大地震影響帅韧,放射性物質發(fā)生泄漏里初。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一忽舟、第九天 我趴在偏房一處隱蔽的房頂上張望双妨。 院中可真熱鬧,春花似錦叮阅、人聲如沸刁品。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挑随。三九已至,卻和暖如春勒叠,著一層夾襖步出監(jiān)牢的瞬間兜挨,已是汗流浹背膏孟。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暑劝,地道東北人骆莹。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像担猛,于是被迫代替她去往敵國和親幕垦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內容

  • 堆排序 堆排序基本簡介 1991年的計算機先驅獎獲得者傅联、斯坦福大學計算機科學系教授羅伯特·弗洛伊德(Robert ...
    BlackMammba閱讀 1,824評論 0 10
  • 概述 排序有內部排序和外部排序先改,內部排序是數(shù)據記錄在內存中進行排序,而外部排序是因排序的數(shù)據很大蒸走,一次不能容納全部...
    蟻前閱讀 5,170評論 0 52
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 將一個記錄插入到已排序好...
    依依玖玥閱讀 1,243評論 0 2
  • 前言 八大排序仇奶,三大查找是《數(shù)據結構》當中非常基礎的知識點比驻,在這里為了復習順帶總結了一下常見的八種排序算法该溯。常見的...
    LeeLom閱讀 97,197評論 41 662
  • 和往常一樣 坐著公交車踏上 回家的路 一抹白色一閃而過 原來是滿樹的 玉蘭花 一片雪白 美極了 不知不覺 春天的腳...
    只想安居一角閱讀 218評論 0 1