圖解堆排序-C語言實現(xiàn)

我們在介紹《什么是優(yōu)先隊列》的時候就注意到翔横,如果每次都刪除堆頂元素,那么將會得到一個有序的數(shù)據(jù)效览。因此荡短,我們可以利用二叉堆來對數(shù)據(jù)進行排序。?點我查看本文代碼地址瘦锹。

堆排序分析

通過前面的學習我們可以看到沼本,如果構(gòu)建一個二叉堆锭沟,最后每次從堆頂取出一個元素,那么最終取出元素就是有序的辫红,不過如果要用來對數(shù)據(jù)按照從小到大排序,就不是構(gòu)造小頂堆切油,而是大頂堆了名惩,即堆頂元素大于等于其左右兒子節(jié)點娩鹉。總結(jié)堆排序思路如下:

以O(shè)(N)時間復雜度構(gòu)建N個元素的二叉堆

以O(shè)(logN)時間復雜度刪除一個堆頂元素戚宦,N個元素時間復雜度為O(NlogN)

由于刪除一個堆頂元素時锈嫩,就會空出一個位置呼寸,為了節(jié)省空間,將刪除的堆頂元素放到數(shù)組末尾

當堆為空時对雪,完成排序

由于數(shù)組元素從下標0開始慌植,因此每個位置必須利用好。假設(shè)堆頂元素位置為i,那么左右兒子節(jié)點位置分別為2i+1,2i+2

實例分析

根據(jù)前面的分析丈钙,我們來看一個具體的例子交汤。假設(shè)我們要對

進行排序芙扎。

該數(shù)據(jù)構(gòu)成的原始二叉樹如下:

構(gòu)建二叉堆

為了能夠使得數(shù)組所有元素滿足堆的性質(zhì)戒洼,即父節(jié)點大于等于兒子節(jié)點,我們需要從倒數(shù)第二層開始調(diào)整(為什么不是從最后一層寥掐?)。即調(diào)整8和10百炬。

對于8來說污它,找到它的兒子節(jié)點中較大的一個衫贬,即35,將8和35交換后如下:

此時數(shù)組數(shù)據(jù)為:

對于10來說,它比左右兒子節(jié)點都大,因此不需要調(diào)整缝呕。

對于1來說斧散,它的右兒子35最大鸡捐,因此需要調(diào)整,和右兒子交換后如下:

此時數(shù)組數(shù)據(jù)為:

但是一次交換后源祈,我們發(fā)現(xiàn)香缺,1的左兒子還是比它大歇僧,因此交換它和較大的左兒子的位置,交換后如下:

此時數(shù)組數(shù)據(jù)為:

最終我們得到了滿足堆性質(zhì)的二叉堆了。

基于二叉堆的排序

在堆創(chuàng)建好后侥钳,每次取出堆頂元素舷夺,并且調(diào)整堆鄙陡,把堆頂元素放在數(shù)組最后即可躏啰。

例如给僵,對于前面創(chuàng)建好的堆,堆頂元素是35蔓同,我們?nèi)〕龅趇(此時為1)個元素35蹲诀,并把堆最后一個元素放在數(shù)組倒數(shù)第i個位置:

為了滿足堆性質(zhì)脯爪,我們需要調(diào)整堆頂元素痕慢,因為堆頂元素目前不滿足堆性質(zhì),因此需要交換8和15的位置:

此時所有元素再次滿足堆性質(zhì)快骗。

此時數(shù)組數(shù)據(jù)為:

對于其他元素也是同樣的操作方篮,因此不再贅述励负。

代碼實現(xiàn)

根據(jù)上面的分析熄守,關(guān)鍵代碼實現(xiàn)如下:

voidadjust_ele(ElementType arr[],inti,intlength){intchild ;? ? ElementType temp;for(temp = arr[i];2*i+1< length;i = child)? ? {? ? ? ? child =2* i +1;/*找到較大的兒子*/if(child != length-1&& arr[child+1] > arr[child])? ? ? ? ? ? child+=1;/*如果空穴元素小于該兒子,則空穴下滑*/if(temp < arr[child])? ? ? ? ? arr[i] = arr[child];elsebreak;? ? }/*將i位置的元素放到正確的位置*/arr[i] = temp;}voidheap_sort(ElementType arr[],intlength){inti =0;/*構(gòu)建堆*/for(i = length /2;i >=0;i--)? ? {? ? ? ? adjust_ele(arr,i,length);//printArr(arr,length);}for(i = length-1;i >0;i--)? ? {/*填充i位置的空穴*/swap(&arr[0],&arr[i]);/*每次都處理堆頂元素*/adjust_ele(arr,0,i);//printArr(arr,length);}}

完整可運行代碼地址:?heapSort

運行結(jié)果:

beforesort:1108571535aftersort:1578101535

總結(jié)

結(jié)合我們前面介紹的優(yōu)先隊列攒发,我們很容易理解堆排序晋南,不過需要注意的就是位置0必須使用上负间。另外通過利用刪除堆頂元素后空出來的位置姜凄,避免了另外申請數(shù)組內(nèi)存來存放排序好的數(shù)組趾访。建議自己修改完整可運行代碼扼鞋,來觀察數(shù)據(jù)調(diào)整情況。

看我主頁簡介免費C++學習資源捐友,視頻教程溃槐、職業(yè)規(guī)劃昏滴、面試詳解猴鲫、學習路線、開發(fā)工具

每晚8點直播講解C++編程技術(shù)影涉。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末变隔,一起剝皮案震驚了整個濱河市规伐,隨后出現(xiàn)的幾起案子蟹倾,更是在濱河造成了極大的恐慌,老刑警劉巖猖闪,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲜棠,死亡現(xiàn)場離奇詭異,居然都是意外死亡培慌,警方通過查閱死者的電腦和手機豁陆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門吵护,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盒音,“玉大人,你說我怎么就攤上這事馅而∠榉蹋” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵瓮恭,是天一觀的道長雄坪。 經(jīng)常有香客問我,道長屯蹦,這世上最難降的妖魔是什么维哈? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任绳姨,我火速辦了婚禮,結(jié)果婚禮上阔挠,老公的妹妹穿的比我還像新娘飘庄。我一直安慰自己,他們只是感情好谒亦,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布竭宰。 她就那樣靜靜地躺著,像睡著了一般份招。 火紅的嫁衣襯著肌膚如雪切揭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天锁摔,我揣著相機與錄音廓旬,去河邊找鬼。 笑死谐腰,一個胖子當著我的面吹牛孕豹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播十气,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼励背,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了砸西?” 一聲冷哼從身側(cè)響起叶眉,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芹枷,沒想到半個月后衅疙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡鸳慈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年饱溢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片走芋。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡绩郎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翁逞,到底是詐尸還是另有隱情肋杖,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布熄攘,位于F島的核電站兽愤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜浅萧,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一逐沙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧洼畅,春花似錦吩案、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至丧肴,卻和暖如春残揉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芋浮。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工抱环, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纸巷。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓镇草,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瘤旨。 傳聞我的和親對象是個殘疾皇子梯啤,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 參考:十大經(jīng)典排序算法 0、排序算法說明 0.1排序的定義 對一序列對象根據(jù)某個關(guān)鍵字進行排序存哲。 0.2 術(shù)語說明...
    誰在烽煙彼岸閱讀 1,014評論 0 12
  • 0因宇、算法概述 0.1 算法分類 十種常見排序算法可以分為兩大類: 非線性時間比較類排序:通過比較來決定元素間的相對...
    Demon_code閱讀 1,050評論 0 2
  • 概述 排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進行排序宏胯,而外部排序是因排序的數(shù)據(jù)很大羽嫡,一次不能容納全部...
    蟻前閱讀 5,186評論 0 52
  • 排序算法說明 (1)排序的定義:對一序列對象根據(jù)某個關(guān)鍵字進行排序本姥; 輸入:n個數(shù):a1,a2,a3,…,an 輸...
    code武閱讀 662評論 0 0
  • 今天休息肩袍,躺了大半天,感覺眼睛都睡腫了婚惫,我那天生大雙眼皮兒睡得跟剛喇的似的氛赐,不說了不說了,我要安歇了先舷,明天還要繼續(xù)...
    哇啦哇啦崩兒嘎不嘎閱讀 78評論 0 0