堆python實(shí)現(xiàn)

  • 堆是一顆完全二叉樹
  • 任意節(jié)點(diǎn)的左孩子和右孩子比該節(jié)點(diǎn)值大時(shí)悔醋,是小頂堆
    任意節(jié)點(diǎn)的左孩子和右孩子比該節(jié)點(diǎn)值小時(shí),是大頂堆
  • 堆數(shù)次序是是二叉樹的層次遍歷
  • 堆存儲(chǔ)在列表中

堆的操作
①heapify:維護(hù)堆狀態(tài),也叫堆化萄唇。先假設(shè)有了一個(gè)完整的堆蝌戒,當(dāng)根節(jié)點(diǎn)變化時(shí)苟径,需要重新維護(hù)堆狀態(tài)的動(dòng)作。
②build_heap:建堆痛黎,建堆需要從底層建起,找到最后一個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)x刮吧,heapify(x)得到x,x_l_child,x_r_child滿足堆結(jié)構(gòu)湖饱,再找x-1節(jié)點(diǎn)y,heapify(y)得到y(tǒng),y_l_child,y_r_child滿足堆結(jié)構(gòu)杀捻,再找x-2井厌,x-3...逆序遍歷后,每次都是底層堆已經(jīng)完整致讥,只有root節(jié)點(diǎn)不滿足大小仅仆,依次heapify后就完成了建堆操作。時(shí)間復(fù)雜度O(n)
③get_top:取堆頂垢袱,彈出堆頂后墓拜,把堆尾移動(dòng)到堆頂,然后heapify
④insert:插入的數(shù)據(jù)和父節(jié)點(diǎn)比較大小请契,不滿足就交換咳榜,然后遞歸比較。直到滿足條件或到走到堆頂

應(yīng)用場(chǎng)景
topK問題爽锥,優(yōu)先級(jí)隊(duì)列

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

class MyHeap(object):
    def __init__(self):
        # i從0開始數(shù),建立大頂堆
        # i從1數(shù),father=i//2;    lchild=i*2;   rchild=i*2+1
        # i從0數(shù),father=(i-1)//2;lchild=i*2+1; rchild=i*2+1+1
        self.data_list = []
        self.top = 0

    def heap_size(self):
        return len(self.data_list) - 1

    def _swap(self, index_a, index_b):
        self.data_list[index_a], self.data_list[index_b] = self.data_list[index_b], self.data_list[index_a]

    def _father(self, i):
        return (i - 1) // 2

    def _lchild(self, i):
        return i * 2 + 1

    def _rchild(self, i):
        return i * 2 + 1 + 1

    # 堆的操作:維護(hù)堆狀態(tài)(堆化),堆的top節(jié)點(diǎn)發(fā)生變化時(shí),重新維護(hù)堆的狀態(tài)
    def heapify(self, root):
        # 如果堆的root不是最大的,那么就和左右孩子中較大的x進(jìn)行交換,然后top改成x涌韩,遞歸堆化,直到?jīng)]有滿足條件或者到底為止
        if root > self.heap_size():
            return
        left_node = self._lchild(root)
        right_node = self._rchild(root)
        largest_node = root

        if left_node <= self.heap_size() and self.data_list[left_node] > self.data_list[largest_node]:
            largest_node = left_node
        if right_node <= self.heap_size() and self.data_list[right_node] > self.data_list[largest_node]:
            largest_node = right_node
        if largest_node != root:
            self._swap(largest_node, root)
            self.heapify(root=largest_node)

    # 堆的操作:建堆氯夷,找到最后一個(gè)node節(jié)點(diǎn)的父節(jié)點(diǎn),然后倒著堆化
    # 因?yàn)榻ǘ咽侵荒軓牡紫峦辖?從上邊之間改堆的節(jié)點(diǎn),堆就會(huì)塌了
    def build_heap(self, data_list):
        self.data_list = data_list
        last_node = self.heap_size()
        last_node_parent = self._father(last_node)
        for i_node in range(last_node_parent, -1, -1):
            self.heapify(i_node)

    # 堆的操作:取堆頂
    def get_heap_top(self):
        if self.heap_size() == 0:
            return None
        res = self.data_list[self.top]
        # 把堆的最后一個(gè)元素和堆頂交換,然后重新堆化
        self.data_list[self.top] = self.data_list.pop()
        self.heapify(self.top)
        return res

    # 堆的操作:插入操作
    def insert(self, data):
        self.data_list.append(data)
        new_data_index = self.heap_size()
        father_index = self._father(new_data_index)
        while self.data_list[father_index] < data and new_data_index != self.top:
            self._swap(father_index, new_data_index)
            new_data_index = father_index
            father_index = self._father(new_data_index)


if __name__ == '__main__':
    data_list = [1, 2, 3, 4, 5, 6, 7]
    s = MyHeap()
    s.build_heap(data_list=data_list)
    print(s.data_list)
    print(s.get_heap_top())
    print(s.get_heap_top())
    print(s.get_heap_top())
    s.insert(data=8)
    print(s.get_heap_top())
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贸辈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌擎淤,老刑警劉巖奢啥,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嘴拢,居然都是意外死亡桩盲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門席吴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赌结,“玉大人,你說我怎么就攤上這事孝冒〖硪Γ” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵庄涡,是天一觀的道長(zhǎng)量承。 經(jīng)常有香客問我,道長(zhǎng)穴店,這世上最難降的妖魔是什么撕捍? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮泣洞,結(jié)果婚禮上忧风,老公的妹妹穿的比我還像新娘。我一直安慰自己球凰,他們只是感情好狮腿,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著呕诉,像睡著了一般蚤霞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上义钉,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天昧绣,我揣著相機(jī)與錄音,去河邊找鬼捶闸。 笑死夜畴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的删壮。 我是一名探鬼主播贪绘,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼央碟!你這毒婦竟也來了税灌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎菱涤,沒想到半個(gè)月后苞也,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粘秆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年如迟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攻走。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡殷勘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昔搂,到底是詐尸還是另有隱情玲销,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布摘符,位于F島的核電站贤斜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏议慰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一奴曙、第九天 我趴在偏房一處隱蔽的房頂上張望别凹。 院中可真熱鬧,春花似錦洽糟、人聲如沸炉菲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拍霜。三九已至,卻和暖如春薪介,著一層夾襖步出監(jiān)牢的瞬間祠饺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工汁政, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留道偷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓记劈,卻偏偏與公主長(zhǎng)得像勺鸦,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子目木,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345