一分鐘了解堆的基本操作

2022-07-03 22:54:16 字數 2804 閱讀 8151

任何乙個資料結構,無非就是增刪改查四大類:

功能方法

時間複雜度

增offer(e e)

o(logn)

刪poll()

o(logn)

改無直接的 api

刪 + 增

查peek()

o(1)

這裡peek()的時間複雜度很好理解,因為堆的用途就是能夠快速的拿到一組資料裡的最大/最小值,所以這一步的時間複雜度一定是o(1)的,這就是堆的意義所在。

那麼我們具體來看offer(e e)poll()的過程。

比如我們新加乙個0到剛才這個最小堆裡面:

那很明顯,0 是要放在最上面的,可是,直接放上去就不是一棵完全二叉樹了啊。。

所以說,

這樣就保證滿足了堆的兩個特點,也就是保證了加入新元素之後它還是個堆

那具體怎麼做呢:

step 1.

先把 0 放在最後接上,別一上來就想著上位;

ok!總算先上岸了,然後我們再一步步往上走。

這裡「能否往上走」的標準在於:

是否滿足堆序性

也就是說,現在 5 和 0 之間不滿足堆序性,那麼交換位置,換到直到滿足堆序性為止

這裡對於最小堆來說的堆序性,就是小的數要在上面

step 2. 與 5 交換

此時 0 和 3 不滿足堆序性了,那麼再交換。

step 3. 與 3 交換

還不行,0 還比 1 小,所以繼續換。

step 4. 與 1 交換

ok!這樣就換好了,乙個新的堆誕生了~

總結一下這個方法:

先把新元素加入陣列的末尾,再通過不斷比較與 parent 的值的大小,決定是否交換,直到滿足堆序性為止。

這個過程就是siftup(),原始碼如下:

時間複雜度

這裡不難發現,其實我們只交換了一條支路上的元素,

也就是最多交換o(height)次。

那麼對於完全二叉樹來說,除了最後一層都是滿的,o(height) = o(logn)

所以offer(e e)的時間複雜度就是o(logn)啦。

poll()就是把最頂端的元素拿走。

對了,沒有辦法拿走中間的元素,畢竟要 vip 先出去,小弟才能出去。

那麼最頂端元素拿走後,這個位置就空了:

我們還是先來滿足堆序性,因為比較容易滿足嘛,直接從最後面拿乙個來補上就好了,先放個傀儡上來。

step1. 末尾元素上位

這樣一來,堆序性又不滿足了,開始交換元素。

那 8 比 7 和 3 都大,應該和誰交換呢?

假設與 7 交換,那麼 7 還是比 3 大,還得 7 和 3 換,麻煩。

所以是與左右孩子中較小的那個交換。

step 2. 與 3 交換

下去之後,還比 5 和 4 大,那再和 4 換一下。

step 3. 與 4 交換

ok!這樣這棵樹總算是穩定了。

總結一下這個方法:

先把陣列的末位元素加到頂端,再通過不斷比較與左右孩子的值的大小,決定是否交換,直到滿足堆序性為止。

這個過程就是siftdown(),原始碼如下:

時間複雜度

同樣道理,也只交換了一條支路上的元素,也就是最多交換o(height)次。

所以offer(e e)的時間複雜度就是o(logn)啦。

我是小齊,紐約程式媛,終生學習者,每天晚上 9 點,雲自習室裡不見不散!

更多乾貨文章見我的 github:

一分鐘sed入門(一分鐘系列)

1.簡介 sed是一種行編輯器,它一次處理一行內容。2.sed呼叫方式 sed options command file s sed options f scriptfile file s 第一種直接在命令列中執行,第二種把命令寫到了指令碼中,二者無本質區別。示例 1 列印hello.txt的內容 ...

一分鐘了解索引技巧

花1分鐘時間,了解聚集索引,非聚集索引,聯合索引,索引覆蓋。舉例,業務場景,使用者表,表結構為 t user uid primary key,login name unique,passwd,login time,age,聚集索引 clustered index 聚集索引決定資料在磁碟上的物理排序,...

一分鐘了解負載均衡

什麼是負載均衡 負載均衡 load balance 是分布式系統架構設計中必須考慮的因素之一,它通常是指,將請求 資料 均勻 分攤到多個操作單元上執行,負載均衡的關鍵在於 均勻 常見的負載均衡方案 常見網際網路分布式架構如上,分為客戶端層 反向 nginx層 站點層 服務層 資料層。可以看到,每乙個...