堆排序

一坐桩、樹相關(guān)知識(shí)

  • 樹的深度(高度):表示樹最深有幾層
  • 樹的度:每個(gè)節(jié)點(diǎn)的分叉數(shù)量叫度,所有節(jié)點(diǎn)中分叉數(shù)量最多的是樹的度
  • 二叉樹:度不超過2的樹(每個(gè)節(jié)點(diǎn)最多有兩個(gè)分叉)
  • 完全二叉樹:葉子節(jié)點(diǎn)只能出現(xiàn)在最下層和次下層封锉,如果從樹根開始按序編號(hào)中間沒有遺漏就是完全二叉樹


  • 滿二叉樹:每一層的節(jié)點(diǎn)都占滿绵跷。也是完全二叉樹

完全二叉樹的存儲(chǔ)

使用列表方式存儲(chǔ),必須存儲(chǔ)完全二叉樹

li = [8,4,12,2,6,10,14,1,3,5]#對(duì)應(yīng)下標(biāo)[0,1,2,3,4,5,6,7,8,9]
  • 基于下標(biāo)成福,父節(jié)點(diǎn)找左孩子節(jié)點(diǎn):
    i -> 2i+1
    基于下標(biāo)碾局,父節(jié)點(diǎn)找右孩子節(jié)點(diǎn):
    i -> 2i+2

  • 基于下標(biāo),左孩子找父節(jié)點(diǎn):
    i-> (i-1)/2
    基于下標(biāo)奴艾,右孩子找父節(jié)點(diǎn):
    i-> (i-2)/2
    孩子找父節(jié)點(diǎn)可以合并為:i->(i-1)//2

二净当、堆的基本概念

堆是一種完全二叉樹

  • 大根堆:任意節(jié)點(diǎn)都比孩子節(jié)點(diǎn)大


  • 小根堆:任意節(jié)點(diǎn)都比孩子節(jié)點(diǎn)小


堆的向下調(diào)整性

根節(jié)點(diǎn)的左右子樹都是堆,根節(jié)點(diǎn)所在的樹自身不是堆蕴潦∠裉洌可以通過一次向下調(diào)整變成一個(gè)堆。


原圖

調(diào)整后的圖

三潭苞、堆排序

構(gòu)造大根堆

從最后一個(gè)有孩子的節(jié)點(diǎn)忽冻,以該節(jié)點(diǎn)為根的樹如果滿足大根堆不做調(diào)整。如果不是大根堆此疹,則利用向下調(diào)整性構(gòu)造一個(gè)大根堆甚颂。
5,4,2,7,0都沒有子節(jié)點(diǎn)蜜猾,單個(gè)節(jié)點(diǎn)本身就是一個(gè)堆,所以從3開始

原圖

構(gòu)造大根堆

挨個(gè)出數(shù)

由于是大根堆振诬,取出的根元素是最大的值蹭睡。圖示第一次取跟元素,取出后剩余元素重新排序赶么,發(fā)現(xiàn)最終得到的不是一個(gè)完全二叉樹肩豁,該方法不符合要求。因?yàn)?strong>堆必須是一個(gè)完全二叉樹辫呻。


為了得到一個(gè)完全二叉樹清钥,當(dāng)取出根元素后,可以利用樹的最后一個(gè)元素頂替上去放闺,再利用向下調(diào)整性重新排序后取出根元素祟昭,不斷重復(fù)。每次取的根元素排列得到升序的結(jié)果怖侦,即實(shí)現(xiàn)了堆排序篡悟。

代碼實(shí)現(xiàn)

def sift(li,low,high):#堆的向下調(diào)整性
    tmp = li[low]
    i = low
    j = 2 * i + 1
    while j <= high:#第二種情況:i指向葉子節(jié)點(diǎn),j指向值已經(jīng)超出high范圍
        if j + 1 <= high and li[j+1] > li[j]:#j指向左右兩個(gè)節(jié)點(diǎn)值最大的位置
            j += 1
        if li[j] > tmp:
            li[i] = li[j]
            i = j
            j = 2 * i + 1
        else:#第一種情況:左右兩個(gè)子節(jié)點(diǎn)都比tmp大
            break
    li[i] = tmp

def heap_sort(li):
    n = len(li)
    #構(gòu)造堆
    for low in range(n//2 - 1,-1,-1):#最后一個(gè)節(jié)點(diǎn)是n-1,找到父節(jié)點(diǎn)n//2 - 1,然后一直到0的位置構(gòu)造堆
        sift(li,low,n-1)#使用整個(gè)數(shù)的最大下標(biāo)n-1作為每個(gè)子樹的high,簡(jiǎn)單且不影響第二種情況判斷
    #挨個(gè)出數(shù)
    for high in range(n-1,-1,-1):#n-1下標(biāo)到0
        li[0],li[high] = li[high],li[0]#當(dāng)前范圍的根元素和high指向的元素?fù)Q位置
        sift(li,0,high-1)#交換后修改high的位置后再重新調(diào)整

向下調(diào)整性兩種退出循環(huán)情況演示:


原圖

第一種終止情況.gif

第二種終止情況.gif

時(shí)間復(fù)雜度

def heap_sort(li):
    ...
    for low in range(n//2 - 1,-1,-1): #O(n)
        sift(li,low,n-1)  #由于while循環(huán)中j = 2 * i + 1匾寝,所以是O(logn)

    for high in range(n-1,-1,-1): #O(n)
        li[0],li[high] = li[high],li[0] #O(1)
        sift(li,0,high-1) #O(log(n))

時(shí)間復(fù)雜度是:O(n*logn)

內(nèi)置模塊實(shí)現(xiàn)

  • 內(nèi)置模塊只能構(gòu)造小根堆
import heapq

li = [0,6,2,7,5,8,3,1]
heapq.heapify(li)#內(nèi)置方法構(gòu)造的是小根堆
print(li)#[0, 1, 2, 6, 5, 8, 3, 7]
heapq.heappush(li,9)#插入一個(gè)元素搬葬,重新構(gòu)造堆
print(li)#[0, 1, 2, 6, 5, 8, 3, 7, 9]
item = heapq.heappop(li)#小根堆根元素出來最小的值,剩下的重新構(gòu)造堆
print(item)#0
print(li)#[1, 5, 2, 6, 9, 8, 3, 7]
  • heappop()挨個(gè)出數(shù)實(shí)現(xiàn)排序
import heapq

li = [0,6,2,7,5,8,3,1]
heapq.heapify(li)
res = [heapq.heappop(li) for i in range(len(li))]
print(res)
>>>[0, 1, 2, 3, 5, 6, 7, 8]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市艳悔,隨后出現(xiàn)的幾起案子急凰,更是在濱河造成了極大的恐慌,老刑警劉巖猜年,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抡锈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡乔外,警方通過查閱死者的電腦和手機(jī)床三,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袁稽,“玉大人勿璃,你說我怎么就攤上這事擒抛⊥破” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵歧沪,是天一觀的道長(zhǎng)歹撒。 經(jīng)常有香客問我,道長(zhǎng)诊胞,這世上最難降的妖魔是什么暖夭? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任锹杈,我火速辦了婚禮,結(jié)果婚禮上迈着,老公的妹妹穿的比我還像新娘竭望。我一直安慰自己,他們只是感情好裕菠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布咬清。 她就那樣靜靜地躺著,像睡著了一般奴潘。 火紅的嫁衣襯著肌膚如雪旧烧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天画髓,我揣著相機(jī)與錄音掘剪,去河邊找鬼。 笑死奈虾,一個(gè)胖子當(dāng)著我的面吹牛夺谁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愚墓,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼予权,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了浪册?” 一聲冷哼從身側(cè)響起扫腺,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎村象,沒想到半個(gè)月后笆环,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厚者,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年躁劣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片库菲。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡账忘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熙宇,到底是詐尸還是另有隱情鳖擒,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布烫止,位于F島的核電站蒋荚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏馆蠕。R本人自食惡果不足惜期升,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一惊奇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧播赁,春花似錦颂郎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至舟奠,卻和暖如春竭缝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沼瘫。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工抬纸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耿戚。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓湿故,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親膜蛔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坛猪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

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

  • 上次寫到了快排,接著往下講皂股。O(nlogn)級(jí)別的算法除了上次說的快排墅茉,歸并,還有推排序呜呐。今天從先推排序開始寫就斤。堆...
    鍋與盆閱讀 2,040評(píng)論 0 2
  • 二叉樹 滿二叉樹 國(guó)內(nèi)教程定義:一個(gè)二叉樹,如果每一個(gè)層的結(jié)點(diǎn)數(shù)都達(dá)到最大值蘑辑,則這個(gè)二叉樹就是滿二叉樹洋机。也就是說,...
    簡(jiǎn)_愛SimpleLove閱讀 4,271評(píng)論 0 3
  • 堆排序基于完全二叉樹 若設(shè)二叉樹的深度為h洋魂,除第 h 層外绷旗,其它各層 (1~h-1) 的結(jié)點(diǎn)數(shù)都達(dá)到最大個(gè)數(shù),第 ...
    alonwang閱讀 141評(píng)論 0 1
  • 本文只是自己的筆記副砍,并不具備過多的指導(dǎo)意義衔肢。為了理解很多都使用了遞歸,而不是自己通過while進(jìn)行壓棧處理址晕。代碼的...
    kirito_song閱讀 2,215評(píng)論 0 8
  • 一膀懈、堆的定義 (1)堆樹是一顆完全二叉樹顿锰; (2)堆樹中某個(gè)節(jié)點(diǎn)的值總是不大于或不小于其孩子節(jié)點(diǎn)的值谨垃; (3)堆樹...
    憂零520閱讀 591評(píng)論 0 1