算法與數(shù)據(jù)結(jié)構(gòu)(六):堆排序


title: 算法與數(shù)據(jù)結(jié)構(gòu)(六):堆排序
tags: [算法與數(shù)據(jù)結(jié)構(gòu), C語(yǔ)言, 堆排序]
date: 2019-03-31 12:32:29
categories: 算法與數(shù)據(jù)結(jié)構(gòu)
keywords: 算法與數(shù)據(jù)結(jié)構(gòu), C語(yǔ)言, 堆排序


上一次說(shuō)到了3種基本的排序算法,三種基本的排序算法時(shí)間復(fù)雜度都是O(n^2)拍嵌,雖然比較簡(jiǎn)單遭赂,但是效率相對(duì)較差,因此后續(xù)有許多相應(yīng)的改進(jìn)算法横辆,這次主要說(shuō)說(shuō)堆排序算法撇他。

堆排序算法是對(duì)選擇排序的一種優(yōu)化。

那么什么是堆呢狈蚤?堆是一種樹(shù)形結(jié)構(gòu)困肩。在維基百科上的定義是這樣的“給定堆中任意節(jié)點(diǎn) P 和 C,若 P 是 C 的母節(jié)點(diǎn)脆侮,那么 P 的值會(huì)小于等于(或大于等于) C 的值”锌畸。

這句話通俗一點(diǎn)就是,樹(shù)的根節(jié)點(diǎn)需要大于(小于)它的孩子節(jié)點(diǎn)靖避,而每個(gè)左右子樹(shù)都滿足這個(gè)條件潭枣。當(dāng)樹(shù)的根節(jié)點(diǎn)大于它的左右孩子節(jié)點(diǎn)時(shí)稱為大頂推比默,否則稱為小頂堆。

排序算法的思路是這樣的盆犁,首先將序列中的元素組織成一個(gè)大頂堆命咐,將樹(shù)的根節(jié)點(diǎn)放到序列的最后面,然后將剩余的元素再組織成一個(gè)大頂堆谐岁,然后放到倒數(shù)第二個(gè)位置醋奠,以此類(lèi)推。

先假定它們的對(duì)應(yīng)關(guān)系如下圖所示:

1.png

我們從樹(shù)的最后一個(gè)非葉子節(jié)點(diǎn)開(kāi)始伊佃,從這個(gè)子樹(shù)中選擇最大的一個(gè)數(shù)窜司,將它交換到子樹(shù)的根節(jié)點(diǎn),也就是如下圖所示

2.png

接著再?gòu)暮笸安檎蚁乱粋€(gè)非葉子節(jié)點(diǎn)

3.png
4.png

經(jīng)過(guò)這樣一輪航揉,一直調(diào)整到樹(shù)的根節(jié)點(diǎn)例证,讓后將根節(jié)點(diǎn)放到序列的最后一個(gè)元素,接著再將剩余元素重新組織為一個(gè)新的堆迷捧,直到所有元素都完成排序

現(xiàn)在已經(jīng)對(duì)堆排序的基本思路有了一定的了解织咧,在寫(xiě)代碼之前需要建立樹(shù)節(jié)點(diǎn)與它在序列中的相關(guān)位置做一個(gè)對(duì)應(yīng)關(guān)系,假設(shè)一個(gè)非葉子節(jié)點(diǎn)在序列中的位置為n漠秋,那么它的兩個(gè)子節(jié)點(diǎn)分別是2n + 1與 2n + 2笙蒙。而且小于n的一定是位于n前方的非葉子節(jié)點(diǎn),所以在調(diào)整堆時(shí)庆锦,從n開(kāi)始一直到0捅位,前面的一定是非葉子節(jié)點(diǎn),根據(jù)這點(diǎn)可以寫(xiě)出這樣的代碼

void HeapSort(int a[], int nLength)
{
//從最后一個(gè)非葉子節(jié)點(diǎn)開(kāi)始調(diào)整
for (int n = nLength / 2 - 1; n >= 0; n--)
{
HeapAdjust(a, n, nLength);
}

for (int n = nLength - 1; n > 0; n--)
{
    //取堆頂與最后一個(gè)葉子節(jié)點(diǎn)互換
    int tmp = a[0];
    a[0] = a[n];
    a[n] = tmp;

    //調(diào)整剩余堆
    HeapAdjust(a, 0, n);
}

}

上述代碼首先取最后一個(gè)葉子節(jié)點(diǎn)搂抒,對(duì)所有非葉子節(jié)點(diǎn)進(jìn)行調(diào)整艇搀,得到堆頂?shù)淖畲笤亍H缓髮⒆畲笤嘏c序列最后一個(gè)做交換求晶,接著使用循環(huán)焰雕,對(duì)序列中剩余元素進(jìn)行同樣的操作。

調(diào)整堆時(shí)芳杏,首先比較子樹(shù)的根節(jié)點(diǎn)與它下面的所有子節(jié)點(diǎn)矩屁,并保存最大數(shù)的位置,然后將最大數(shù)與根節(jié)點(diǎn)的數(shù)進(jìn)行交換爵赵,這樣一直進(jìn)行吝秕,直到完成了堆根節(jié)點(diǎn)的交換。

void HeapAdjust(int a[], int nIdx, int nLength)
{
    int child = 0; //child 保存當(dāng)前最大數(shù)的下標(biāo)
    while (2 * nIdx + 1 < nLength)
    {
        child = 2 * nIdx + 1;
        //先找子節(jié)點(diǎn)的最大值(保證存在右節(jié)點(diǎn)的情況下)
        if (child < nLength - 1 && a[child] < a[child + 1])
        {
            child++;
        }

        if (a[nIdx] < a[child])
        {
            int tmp = a[nIdx];
            a[nIdx] = a[child];
            a[child] = tmp;
        }else
        {
            break;
        }

        //如果進(jìn)行了交換空幻,為了防止對(duì)子節(jié)點(diǎn)對(duì)應(yīng)子樹(shù)的破壞烁峭,要對(duì)子樹(shù)也進(jìn)行調(diào)整
        nIdx = child;
    }
}

從算法上來(lái)看,它循環(huán)的次數(shù)與堆的深度有關(guān)秕铛,而二叉樹(shù)的深度應(yīng)該是log2(n) 向下取整约郁,所以調(diào)整的時(shí)候需要進(jìn)行l(wèi)og2(n)次調(diào)整耘柱,而外層需要從0一直到n - 1的位置每次都需要重組堆并進(jìn)行調(diào)整,所以它的時(shí)間復(fù)雜度應(yīng)該為O(nlogn), 它在效率上比選擇排序要高棍现,它的速度主要體現(xiàn)在每次查找選擇最大的數(shù)這個(gè)方面。
<hr />

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末镜遣,一起剝皮案震驚了整個(gè)濱河市己肮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悲关,老刑警劉巖谎僻,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異寓辱,居然都是意外死亡艘绍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)秫筏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)诱鞠,“玉大人,你說(shuō)我怎么就攤上這事这敬『蕉幔” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵崔涂,是天一觀的道長(zhǎng)阳掐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)冷蚂,這世上最難降的妖魔是什么缭保? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮蝙茶,結(jié)果婚禮上艺骂,老公的妹妹穿的比我還像新娘。我一直安慰自己隆夯,他們只是感情好彻亲,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著吮廉,像睡著了一般苞尝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宦芦,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天宙址,我揣著相機(jī)與錄音,去河邊找鬼调卑。 笑死抡砂,一個(gè)胖子當(dāng)著我的面吹牛大咱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播注益,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼碴巾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了丑搔?” 一聲冷哼從身側(cè)響起厦瓢,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啤月,沒(méi)想到半個(gè)月后煮仇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谎仲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年浙垫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片郑诺。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夹姥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辙诞,到底是詐尸還是另有隱情佃声,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布倘要,位于F島的核電站圾亏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏封拧。R本人自食惡果不足惜腿准,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一像樊、第九天 我趴在偏房一處隱蔽的房頂上張望佩微。 院中可真熱鬧残吩,春花似錦、人聲如沸捧杉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)味抖。三九已至评甜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仔涩,已是汗流浹背忍坷。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人佩研。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓柑肴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親旬薯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晰骑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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

  • 一些概念 數(shù)據(jù)結(jié)構(gòu)就是研究數(shù)據(jù)的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)以及它們之間相互關(guān)系,并對(duì)這種結(jié)構(gòu)定義相應(yīng)的運(yùn)算绊序,而且確保經(jīng)過(guò)這...
    Winterfell_Z閱讀 5,854評(píng)論 0 13
  • 1)這本書(shū)為什么值得看: Python語(yǔ)言描述硕舆,如果學(xué)的Python用這本書(shū)學(xué)數(shù)據(jù)結(jié)構(gòu)更合適 2016年出版,內(nèi)容...
    孫懷闊閱讀 12,506評(píng)論 0 15
  • 概述 排序有內(nèi)部排序和外部排序政模,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大蚂会,一次不能容納全部...
    蟻前閱讀 5,191評(píng)論 0 52
  • 排序的基本概念 在計(jì)算機(jī)程序開(kāi)發(fā)過(guò)程中淋样,經(jīng)常需要一組數(shù)據(jù)元素(或記錄)按某個(gè)關(guān)鍵字進(jìn)行排序,排序完成的序列可用于快...
    Jack921閱讀 1,435評(píng)論 1 4
  • 概述 排序有內(nèi)部排序和外部排序胁住,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序趁猴,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    閑云清煙閱讀 758評(píng)論 0 6