重拾數(shù)據(jù)結(jié)構(gòu)之堆排序

大學(xué)的時(shí)候很多學(xué)長就跟我們講打好基礎(chǔ),基礎(chǔ)決定了未來的成長的高度克锣,工作幾年來也參加了不少面試,那么多面試腔长,首先都是基礎(chǔ)袭祟,甚至有的面試全部算法和數(shù)據(jù)結(jié)構(gòu),也許大學(xué)里學(xué)的挺扎實(shí)的捞附,工作后算法用的少巾乳,很多東西都忘了您没。所以需要慢慢的拾起來。
排序中被問得最多的是快速排序和堆排序胆绊,對于堆排序氨鹏,大學(xué)都學(xué)過,大概知道就是有大根堆压状,小根堆以及重建堆仆抵,很多人也就記得一個(gè)大概,讓具體寫就不知道怎么寫了种冬。

1.定義

堆邏輯上可以看成滿二叉樹肢础,所以有k個(gè)節(jié)點(diǎn),那么父節(jié)點(diǎn)就是k/2碌廓,堆的定義中要求每個(gè)節(jié)點(diǎn)
大根堆:1.a[k] >= a[2k] && a[k] >= a[2k+1]
小根堆:1.a[k] <= a[2k] && a[k] <= a[2k+1]



堆排序并不是指這個(gè)堆是有序的传轰,它的排序是不斷的把根節(jié)點(diǎn)移到末尾然后重建剩余的堆,使之繼續(xù)構(gòu)造大根堆或者小根堆谷婆,再次移除慨蛙,重建,每次移出來的都是剩余中最大的或者最小的纪挎,數(shù)據(jù)就有序了期贫。

2.建初始堆

堆排序首先要解決的問題,建初始堆异袄,就是把最初的數(shù)據(jù)建成大根堆或者小根堆通砍。那小根堆來說,根據(jù)定義烤蜕,需要讓父節(jié)點(diǎn)小于子節(jié)點(diǎn)封孙,所以我們重建堆或者調(diào)整堆就是調(diào)整父節(jié)點(diǎn)和子結(jié)點(diǎn)的位置。

//調(diào)整lst[s..m]為一個(gè)小根堆
void HeadAdjust(int *lst, int s, int m) {
    int t = lst[s];
    for (int j = 2 * s; j < m; j *= 2) {  //對j的子結(jié)點(diǎn)進(jìn)行篩選
        //如果右結(jié)點(diǎn)小于左節(jié)點(diǎn)讽营,j+1,j始終記錄的是最小的結(jié)點(diǎn)下標(biāo)
        if (j < m && lst[j] > lst[j+1]) 
            ++j;
        //如果左右結(jié)點(diǎn)中最小的結(jié)點(diǎn)都比父節(jié)點(diǎn)小虎忌,不用調(diào)整
        if (t <= lst[j]) break; 
       //需要調(diào)整,t已經(jīng)記錄了最初的lst[s]的值,直接覆蓋橱鹏,s記錄了上次調(diào)整的下標(biāo)
        lst[s] = lst[j];
        s = j;
    }
    lst[s] = t;   //調(diào)整結(jié)束膜蠢,s就是t最終的位置。
}

設(shè)想如果一個(gè)二叉樹莉兰,如果最下層的結(jié)點(diǎn)都是小根堆挑围,那么只需依次從最下層往上調(diào)整,最終就能調(diào)整為一個(gè)小根堆糖荒,即根節(jié)點(diǎn)就是最小的結(jié)點(diǎn)杉辙。所以建初始堆的代碼:

void InitHeap(int *lst, int size) {
    //從最下層開始調(diào)整,依次往上寂嘉,直到根節(jié)點(diǎn)
    for (int i = size/2; i > 0; --i) {
        HeadAdjust(lst, i, size);
    }
}

3.調(diào)整堆

初始小根堆建成以后奏瞬,根節(jié)點(diǎn)就是最小的節(jié)點(diǎn)枫绅,我們?nèi)〕龈?jié)點(diǎn)移到數(shù)組尾部,然后重建剩余的堆硼端,使之成繼續(xù)為小根堆并淋,如此往復(fù)直到只剩最后一個(gè)節(jié)點(diǎn)。

void ReBuildHeap(int *lst, int size) {
    //從最下層開始調(diào)整珍昨,依次往上县耽,直到根節(jié)點(diǎn)
    for (int i = size; i > 1; --i) {
        //根結(jié)點(diǎn)和最后一個(gè)節(jié)點(diǎn)交換,調(diào)整1..i-1為小根堆镣典。
        std::swap(lst[i], list[1];
        HeadAdjust(lst, 1, i-1);
    }
  //執(zhí)行結(jié)束兔毙,lst從1到size依次從大到小
}

完整代碼:

int main(int argc, char* argv[])
{
    int list[10];
    for (int i = 1; i < 10; ++i) {
        list[i] = rand() % 10;
        printf("%d ", list[i]);
    }
    for (int i = 9/2; i > 0; --i) {
        HeadAdjust(list, i, 9);
    }
    std::cout << list[1] << std::endl;
    for (int i = 9; i > 1; --i) {
        std::swap(list[1], list[i]);
        printf("\n%d", list[i]);
        HeadAdjust(list, 1, i - 1);
    }
    return 0;
}

也算自己的一次加深理解吧,理解記憶兄春,只有真的理解了澎剥,才能記憶的更長久!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赶舆,一起剝皮案震驚了整個(gè)濱河市哑姚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芜茵,老刑警劉巖叙量,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異九串,居然都是意外死亡绞佩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門猪钮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來品山,“玉大人,你說我怎么就攤上這事躬贡∽话拢” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵拂玻,是天一觀的道長。 經(jīng)常有香客問我宰译,道長檐蚜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任沿侈,我火速辦了婚禮闯第,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缀拭。我一直安慰自己咳短,他們只是感情好填帽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咙好,像睡著了一般篡腌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勾效,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天嘹悼,我揣著相機(jī)與錄音,去河邊找鬼层宫。 笑死杨伙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的萌腿。 我是一名探鬼主播限匣,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毁菱!你這毒婦竟也來了米死?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鼎俘,失蹤者是張志新(化名)和其女友劉穎哲身,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贸伐,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勘天,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捉邢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脯丝。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伏伐,靈堂內(nèi)的尸體忽然破棺而出宠进,到底是詐尸還是另有隱情,我是刑警寧澤藐翎,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布材蹬,位于F島的核電站,受9級特大地震影響吝镣,放射性物質(zhì)發(fā)生泄漏堤器。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一末贾、第九天 我趴在偏房一處隱蔽的房頂上張望闸溃。 院中可真熱鬧,春花似錦、人聲如沸辉川。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乓旗。三九已至府蛇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寸齐,已是汗流浹背欲诺。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渺鹦,地道東北人扰法。 一個(gè)月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像毅厚,于是被迫代替她去往敵國和親塞颁。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

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

  • 四. 走向世界之巔——快速排序 你可能會以為歸并排序是最強(qiáng)的算法了吸耿,其實(shí)不然祠锣。回想一下咽安,歸并的時(shí)間效率雖然高伴网,但空...
    Leesper閱讀 1,679評論 9 7
  • 概述:排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序妆棒,而外部排序是因排序的數(shù)據(jù)很大澡腾,一次不能容納全部...
    每天刷兩次牙閱讀 3,732評論 0 15
  • 概述 排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序糕珊,而外部排序是因排序的數(shù)據(jù)很大动分,一次不能容納全部...
    蟻前閱讀 5,186評論 0 52
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 將一個(gè)記錄插入到已排序好...
    依依玖玥閱讀 1,258評論 0 2
  • 本以為晨鐘初敲, 華服高冠红选, 長街盡頭澜公, 騎一匹白馬而來。 未曾想夕陽時(shí)分喇肋, 布衣長衫坟乾, 青石橋下, 泛一葉扁舟而...
    秋水飲馬閱讀 647評論 4 18