什麼是堆?
堆是一棵完全二叉樹,並滿足
n od
ei>=n
ode2
∗i+1
andn
odei
>=n
ode2
∗i+2
>=node_ \quad and \quad node_i>=node_}
nodei
>=n
ode2
∗i+1
and
node
i>=n
ode2
∗i+2
(大頂堆)或者nod
ei<=n
ode2
∗i+1
andn
odei
<=n
ode2
∗i+2
<=node_ \quad and \quad node_i<=node_}
nodei
<=n
ode2
∗i+1
and
node
i<=n
ode2
∗i+2
(小頂堆)
陣列儲存
堆可以做什麼?
可以用來排序,可以用來找到第k大元素
整個資料在陣列上進行,找到最後乙個非葉節點
將該非葉節點和左右孩子比較,若小於孩子則和孩子交換
然後從該節點開始遞迴檢查該子樹是否滿足大頂堆,若不滿足則進行交換,直到葉子
接著從上乙個非葉節點檢查,重複1、2
直到根節點,整棵樹滿足大頂堆
//另注意golang有原生的容器heap
//import "container/heap"
package main
import
"fmt"
//加入,加入元素到最後,然後上浮操作
func
add(nums[
]int
,val int)[
]int
}return nums
}func
del(nums[
]int
)int
if k
>nums[i]
else
}return max
}func
main()
var bighead [
]int
for i:=
0;i<
len(nums)
;i++
fmt.
println
(bighead)
fmt.
println
(del
(bighead)
) fmt.
println
(bighead)
//去除最後乙個
bighead=bighead[
:len
(bighead)-1
] fmt.
println
(del
(bighead)
) fmt.
println
(bighead)
}
在堆的基礎上,交換根和最後乙個節點
在除最後乙個節點的節點上,重新調整堆
重複0、1,知道堆只剩下根,這是整個陣列就都是有序了(大頂堆的操作結果未非遞減,小頂堆的操作結果是非遞增)
維基百科-堆
**排序演算法(三)之堆排序
//以下是按堆的模式寫的程式
//最終是堆,但太浪費了,堆只需要新增和刪除兩個操作
//並且,以為已經有序,會保持堆的特性,而無序遞迴檢查
package main
import
"fmt"
//遞迴監測,交換到底
func
change
(nums [
]int
,i,j int
) l:=
2*i+
1if l
change
(nums, l,j)
} r:=
2*i+
2if r
change
(nums, r,j)}}
//從最後乙個非葉節點,換到頂
func
build
(nums [
]int)[
]int
return nums
}//堆排序
func
findallmax
(nums[
]int)[
]int
return nums
}func
main()
) fmt.
println
(bighead)
fmt.
println
(findallmax
(bighead))}
/*[9 6 8 4 5]
[4 5 6 8 9]
*/
堆及堆排序
堆是一種特殊的資料結構,它是完全二叉樹,可以用一維陣列來儲存,因為二叉樹的性質,所以根據陣列下標就可以確定位置,下面 是關於堆的實現,刪除的過程其實就是將堆的根節點取出的過程,這時的順序就是有序的,如果是最小堆,那麼就是從小到大排序,反之,就是從大到小 1 include 2 3int h 101 ...
堆的實現及堆排序
前兩天刷筆試題,判斷乙個陣列的序列可以構成堆。仔細想了想,腦海裡幾乎已經遺忘了堆的知識,今天又重新去看書,把堆的知識總結一下。首先堆是一種陣列物件,它可以被看成乙個完全二叉樹。在我們常見的堆中有大堆和小堆。對大堆來說,每個父節點都大於孩子結點 小堆恰好相反。而且,大堆 小堆的每個子樹也是乙個大堆 小...
堆(資料結構)及堆排序
這裡的堆是指一種資料結構 或資料結構屬性 非指堆記憶體。堆屬性用二叉樹來體現,具堆屬性的資料結構才可被叫做為堆。具堆屬性的資料結構滿足以下筆記的 順序 和 形狀 兩個條件。將某資料結構如陣列,將陣列的元素依次安排在二叉樹中的根結點 根結點的左孩子 根結點的右孩子位置之上,再將剩餘元素依次安排在根結點...