結(jié)構(gòu)

完全二叉樹(并不是滿二叉樹)
底層是數(shù)組

分類

  • 最大堆
    每個結(jié)點的值都大于或等于其左右孩子結(jié)點的值
  • 最小堆
    每個結(jié)點的值都小于或等于其左右孩子結(jié)點的值

最大堆性質(zhì)

父節(jié)點大于所有子節(jié)點瓮恭,但是左右子節(jié)點

功能:

維護(hù)動態(tài)數(shù)據(jù)的最大最小值,可以考慮使用堆
調(diào)整堆的時間復(fù)雜度O(logk)

堆的操作(以小頂堆為例)

https://www.acwing.com/blog/content/308/

heap[++size] = x;up(size); //插入一個數(shù)
heap[1]; //求最小值
heap[1] = heap[size];size--;down(1); //刪除最小值
heap[k] = heap[size];size--;down(k);up(k); //刪除任意一個元素
heap[k] = x;down(k);up[k]; //修改任意一個元素
  • down和up的時間復(fù)雜度為O(logn)最多交換深度h - 1次,h為n的log函數(shù)

down()

循環(huán)down

  • 圖1 循環(huán)down,注意是fa的左側(cè)子節(jié)點存在,即<heapSize的時候.其實還是遞歸比較好理解
  • 注意else的break;
  • 注意nums[ minmum ] 而不是u,因為兩個minmum可能因為賦值會不一樣
void down(vector<int>& nums, int u, int heapSize) {
    //圖1 循環(huán)down,注意是fa的左側(cè)子節(jié)點存在,即<heapSize的時候.其實還是遞歸比較好理解
    //注意else的break;
    //注意nums[  minmum   ] 而不是u,因為兩個minmum可能因為賦值會不一樣
    while (u * 2 + 1 < heapSize) {
        int l = u * 2 + 1, r = u * 2 + 2, minmum = u;
        if (l < heapSize && nums[l] < nums[minmum]) {
            minmum = l;
        }
        if (r < heapSize && nums[r] < nums[minmum]) {
            minmum = r;
        }

        if (u != minmum) {
            swap(nums[u], nums[minmum]);
            u = minmum;
        }
        else {
            break;
        }
    }
}
圖1

遞歸down

void down(vector<int>& nums, int u, int heapSize) {
    // 遞歸down
    int l = u * 2 + 1, r = u * 2 + 2, minmum = u;
    if (l < heapSize && nums[l] < nums[minmum]) {
        minmum = l;
    }
    if (r < heapSize && nums[r] < nums[minmum]) {
        minmum = r;
    }
    if (u != minmum) {
        swap(nums[u], nums[minmum]);
        down(nums, minmum, heapSize);
    }
}

up()

循環(huán)up

void up(vector<int>& nums, int u, int heapSize) {
    while (u && nums[(u - 1) / 2] > nums[u]) {
        swap(nums[(u - 1) / 2], nums[u]);
        u = u - 1 / 2;
    }        
}

遞歸up

void up(vector<int>& nums, int u, int heapSize) {
    int fa = (u - 1) / 2;
    if (u != 0 && nums[fa] > nums[u]) {
        swap(nums[fa], nums[u]);
        up(nums, fa, heapSize);
    }  
}

建堆

https://www.acwing.com/activity/content/code/content/493331/

  • 時間復(fù)雜度為O(n),為什么?


void buildMinHeap(vector<int>& nums, int heapSize) {
    for (int i = heapSize / 2; i >= 0; --i) {
         down(nums, i, heapSize);
    }
}

heapify

使得數(shù)組“堆有序”

  • 一定是全部有序嗎盒音?為什么
    不是沥邻,無法確定子節(jié)點左右大小
  • 那堆排序如何實現(xiàn)腔呜?
    小頂堆,交換top和rear的位置,size--;down(top).這樣數(shù)組從大到小排列
    交換n次,每次down的時間復(fù)雜度為O(logn)時間復(fù)雜度為O(nlogn)


較小值下沉
void maxHeapify(vector<int>& a, int i, int heapsize) {
    //如果是基1的,那么l = i * 2, r = i * 2 + 1
    int l = i * 2 + 1, r = i * 2 + 2, largest = i;
    if (l < heapSize && a[l] > a[largest]) {
        largest = l;
    }
    if (r < heapSize && a[r] > a[largest]) {
        largest = r;
    }
    if (largest != i) {
        //交換i和字節(jié)中的最大值
        swap(a[largest], a[i]);
        //較小值下沉
        maxHeapify(a, largest, heapSize);
    }
}

buildheap

void buildMaxHeap(vector<int>& a, int heapSize) {
    for (int i = heapSize / 2; i >= 0; --i) {
        maxHeapify(a, i, heapSize);
    } 
}
  • heapsize不減的話一定會多做兩次heapify敬察。(其實問題不大)

LeetCode相關(guān)題目

215. 數(shù)組中的第K個最大元素

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市当纱,隨后出現(xiàn)的幾起案子道媚,更是在濱河造成了極大的恐慌,老刑警劉巖碾盐,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晃跺,死亡現(xiàn)場離奇詭異,居然都是意外死亡毫玖,警方通過查閱死者的電腦和手機(jī)掀虎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來付枫,“玉大人烹玉,你說我怎么就攤上這事〔玻” “怎么了二打?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掂榔。 經(jīng)常有香客問我继效,道長,這世上最難降的妖魔是什么装获? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任瑞信,我火速辦了婚禮,結(jié)果婚禮上穴豫,老公的妹妹穿的比我還像新娘凡简。我一直安慰自己逼友,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布秤涩。 她就那樣靜靜地躺著帜乞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪筐眷。 梳的紋絲不亂的頭發(fā)上黎烈,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機(jī)與錄音匀谣,去河邊找鬼怨喘。 笑死,一個胖子當(dāng)著我的面吹牛振定,可吹牛的內(nèi)容都是我干的必怜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼后频,長吁一口氣:“原來是場噩夢啊……” “哼梳庆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起卑惜,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤膏执,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后露久,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體更米,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年毫痕,在試婚紗的時候發(fā)現(xiàn)自己被綠了征峦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡消请,死狀恐怖栏笆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情臊泰,我是刑警寧澤蛉加,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站缸逃,受9級特大地震影響针饥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜需频,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一丁眼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贺辰,春花似錦户盯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吃靠,卻和暖如春硫眨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巢块。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工礁阁, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人族奢。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓姥闭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親越走。 傳聞我的和親對象是個殘疾皇子棚品,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353

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

  • 堆的時間復(fù)雜度操作所花的時間都和樹的深度成正比 ,因此為O(logn) 初始化小根堆的時間復(fù)雜度O(n) 堆排序[...
    Tsukinousag閱讀 154評論 0 2
  • 思考? ? 設(shè)計一種數(shù)據(jù)結(jié)構(gòu),用來存放整數(shù)廊敌,要求提供 3 個接口 添加元素 獲取最大值 刪除最大值 ? 有沒有更優(yōu)...
    鼬殿閱讀 260評論 0 1
  • 基礎(chǔ)堆排序和 Heapify 這一節(jié)我們介紹兩個使用堆或者說基于堆的思想進(jìn)行排序的算法。 思路1:一個一個地往最大...
    李威威閱讀 7,650評論 0 4
  • 前言:題圖無關(guān)肋殴,接下來開始簡單學(xué)習(xí)學(xué)習(xí)優(yōu)先隊列和堆的相關(guān)數(shù)據(jù)結(jié)構(gòu)的知識囤锉; 前序文章: 數(shù)據(jù)結(jié)構(gòu)與算法(1)——數(shù)組...
    我沒有三顆心臟閱讀 2,137評論 1 15
  • 堆簡述 堆(heap)的結(jié)構(gòu)是一個完全二叉樹的結(jié)構(gòu)。 堆分大根堆和小根堆护锤。如果一個二叉樹它即不是大根堆嚼锄,也不是小根...
    Robin92閱讀 485評論 0 1