二叉堆的理解與實(shí)現(xiàn)

什么是二叉堆

二叉堆是一種特殊的堆僧凤,它的父節(jié)點(diǎn)的值總是大于等于(或小于等于它的子節(jié)點(diǎn)值,稱作小頂堆)元扔,這種堆叫做大頂堆躯保。由于它具有完全二叉樹的性質(zhì),所以可以使用數(shù)組來存儲(chǔ)澎语。當(dāng)父節(jié)點(diǎn)的下標(biāo)為i途事,其左孩子的下標(biāo)為2i验懊,右孩子的下標(biāo)為2i+1。
二叉堆在查找元素的時(shí)候尸变,和普通的數(shù)組一樣鲁森,時(shí)間復(fù)雜度為o(n),但是在獲取最大(最姓穸琛)元素的時(shí)候歌溉,時(shí)間復(fù)雜度是o(1)。二叉堆每次插入和刪除元素的時(shí)候骑晶,都需要對(duì)二叉堆進(jìn)行一次調(diào)整痛垛,其時(shí)間復(fù)雜度為o(log(2n))。

二叉堆的插入與刪除(最大堆舉例)

  • 二叉堆的插入步驟
  1. 首先把需要插入的元素放到二叉樹的最末端(也就是數(shù)組中所有元素的最后)
  2. 從最末端去向上調(diào)整桶蛔,具體來說就是不斷將該節(jié)點(diǎn)和其父節(jié)點(diǎn)比較匙头,如果父節(jié)點(diǎn)的值比插入節(jié)點(diǎn)的值小(對(duì)最小堆來說仔雷,父節(jié)點(diǎn)值比插入節(jié)點(diǎn)值大)蹂析,就將父節(jié)點(diǎn)移動(dòng)到當(dāng)前位置,然后繼續(xù)向上比較碟婆。否則到第3步电抚。
    3.如果當(dāng)前父節(jié)點(diǎn)值比插入節(jié)點(diǎn)值大(對(duì)最小堆來說,插入點(diǎn)值比插入節(jié)點(diǎn)值惺病)蝙叛,就說明當(dāng)前位置適合放入該插入的節(jié)點(diǎn)。那么將當(dāng)前節(jié)點(diǎn)的值替換為插入節(jié)點(diǎn)的值公给,即完成插入操作借帘。
  • 二叉堆的刪除步驟
  1. 首先查找到需要?jiǎng)h除的元素的在數(shù)組中對(duì)應(yīng)的下標(biāo)。
    2.將該下標(biāo)對(duì)應(yīng)的元素?fù)Q成二叉樹最末端的元素(即數(shù)組中最后一個(gè)元素)淌铐。
    3.從當(dāng)前下標(biāo)的位置向下去調(diào)整肺然,具體來說,首先計(jì)算出當(dāng)前下標(biāo)的左孩子的下標(biāo)腿准,如果當(dāng)前節(jié)點(diǎn)有右孩子际起,那么比較左孩子和右孩子誰更大。將插入節(jié)點(diǎn)的值與左孩子和右孩子中最大的元素相比較释涛,如果插入節(jié)點(diǎn)的值更屑尤(對(duì)最小堆來說倦沧,插入節(jié)點(diǎn)值比當(dāng)前孩子節(jié)點(diǎn)值大)唇撬,那么將孩子節(jié)點(diǎn)的值放至其父親節(jié)點(diǎn),更新當(dāng)前下標(biāo)為替換的孩子節(jié)點(diǎn)下標(biāo)展融,然后繼續(xù)向下調(diào)整窖认。否則到第4步。
    4.將插入節(jié)點(diǎn)與左孩子和右孩子中最大的元素相比較,如果插入節(jié)點(diǎn)的值更大(對(duì)最小堆來說扑浸,插入節(jié)點(diǎn)值比當(dāng)前節(jié)點(diǎn)值大)烧给,說明插入節(jié)點(diǎn)應(yīng)該放到當(dāng)前位置。放入之后喝噪,即完成刪除操作础嫡。

c++實(shí)現(xiàn)二叉堆的插入與刪除

#include <iostream>
#include <vector>
using namespace std;

class Max_Heap{
private:
    vector<int> nums;
    int size;
public:
    Max_Heap(): size(0){}
    ~Max_Heap() {
        nums.clear();
        size = 0;
    };

    int get_size() const{
        return size;
    }

    void maxheap_filterup(int index){
        int curr_index = index;
        int data = nums[curr_index];
        int parent_index = (curr_index - 1) / 2;

        while(curr_index > 0){
            if(nums[parent_index] >= data)
                break;
            else{
                nums[curr_index] = nums[parent_index];
                curr_index = parent_index;
                parent_index = (curr_index - 1) / 2;
            }
        }
        nums[curr_index] = data;
    }

    void insert(int x){
      // 先放末端,再向上調(diào)整
        nums.push_back(x);
        ++size;
        // 向上調(diào)整
        maxheap_filterup(size-1);
    }

    int get_data_index(int data)const{
        int j = 0;
        for (j ; j < size ; ++j) {
            if(nums[j] == data)
                break;
        }

        return j;
    }


    void maxheap_filterdown(int start, int end){
        int curr_index = start;
        int child_index_l = 2*curr_index + 1;
        int data = nums[curr_index];

        while(child_index_l <= end){
          // 找到當(dāng)前節(jié)點(diǎn)中左右孩子最大的元素下標(biāo)
            if(child_index_l < end && nums[child_index_l+1] >= nums[child_index_l])
                ++child_index_l;
            if(data >= nums[child_index_l])
                break;
            else{
                nums[curr_index] = nums[child_index_l];
                curr_index = child_index_l;
                child_index_l = child_index_l*2 + 1;
            }
        }
        nums[curr_index] = data;
    }

    void remove(int x){
        //先用最后一個(gè)元素替換刪除位置的元素酝惧,再向下調(diào)整
        int index = get_data_index(x);
        nums[index] = nums[size - 1];
        --size;
        maxheap_filterdown(index, size-1);
    }

    void show()const{
        cout<<"current max heap is:\n";
        for (int i = 0; i < size ; ++i) {
            cout<<nums[i]<<" ";
        }
        cout<<endl;
    }

};
int main() {

    Max_Heap max_heap;
    vector<int> n = {80, 90, 10, 40, 50, 20, 30, 70, 60,85};
    //vector<int> n = {90,85,70,60,80,30,20,10,50,40};
    for (int i = 0; i < n.size(); ++i) {
        max_heap.insert(n[i]);
    }
    max_heap.show();
    max_heap.remove(60);
    max_heap.show();
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末榴鼎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子晚唇,更是在濱河造成了極大的恐慌巫财,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哩陕,死亡現(xiàn)場(chǎng)離奇詭異平项,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)悍及,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門闽瓢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人心赶,你說我怎么就攤上這事鸳粉。” “怎么了园担?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵届谈,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我弯汰,道長(zhǎng)艰山,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任咏闪,我火速辦了婚禮曙搬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鸽嫂。我一直安慰自己纵装,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布据某。 她就那樣靜靜地躺著橡娄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪癣籽。 梳的紋絲不亂的頭發(fā)上挽唉,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天滤祖,我揣著相機(jī)與錄音,去河邊找鬼瓶籽。 笑死匠童,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的塑顺。 我是一名探鬼主播汤求,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼严拒!你這毒婦竟也來了首昔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤糙俗,失蹤者是張志新(化名)和其女友劉穎勒奇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巧骚,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赊颠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了劈彪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竣蹦。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沧奴,靈堂內(nèi)的尸體忽然破棺而出痘括,到底是詐尸還是另有隱情,我是刑警寧澤滔吠,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布纲菌,位于F島的核電站,受9級(jí)特大地震影響疮绷,放射性物質(zhì)發(fā)生泄漏翰舌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一冬骚、第九天 我趴在偏房一處隱蔽的房頂上張望椅贱。 院中可真熱鬧,春花似錦只冻、人聲如沸庇麦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽山橄。三九已至,卻和暖如春住诸,著一層夾襖步出監(jiān)牢的瞬間驾胆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工贱呐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丧诺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓奄薇,卻偏偏與公主長(zhǎng)得像驳阎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子馁蒂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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