大根堆與小根堆必須是完全二叉樹
大根堆的父節點永遠比子節點大或相等
小根堆的父節點永遠比子節點小或相等
本文皆以大根堆為例尾部增加元素
調整為大根堆:與父節點比對,若大於父節點則交換位置,直到小於等於父節點或沒有父節點時停止
void
push
(int value)
void
heapinsert
(int
arr,
int i)
}
時間複雜度:o(logn) 空間複雜度:o(1)
根節點與尾節點交換,刪除尾節點
調整為大根堆:根節點與子節點比較,與比他大的最大子節點交換,直到無子節點比父子節點大,或孩子不存在時結束
int
pop(
)void
heapify
(int
arr,
int index,
int heapsize)
swap
(arr, win, index)
; index = win;
left = index *2+
1;}}
時間複雜度:o(logn) 空間複雜度:o(1)
從上往下建堆
void
heapsort
(int
arr)
int heapsize = arr.length;
while
(heapsize >0)
}
時間複雜度:o(nlogn),空間複雜度:o(1)
從下往上建堆
void
heapsort
(int
arr)
while
(heapsize >0)
}
時間複雜度:o(nlogn),空間複雜度:o(1)
改進版與標準版同為o(nlogn),到底快在哪兒?快在建堆
標準版是從上往下建堆,o(nlogn)
第1層,1個節點,操作1次(看自己一眼,沒法往上公升)
第2層,2個節點,操作2次 (看自己一眼,上公升1次)
…第n-2層,2^(n-3)個節點,操作n-2次(看自己一眼,上公升n-3次)
第n-1層,2^(n-2)個節點,操作n-1次(看自己一眼,上公升n-2次)
第n層,2^(n-1)個節點,操作n次(看自己一眼,上公升n-1次)
改進版是從下往上建堆,o(n)
第1層,1個節點,操作n次(看自己一眼,下沉n-1次)
第2層,2個節點,操作n-1次 (看自己一眼,下沉n-2次)
…第n-2層,2^(n-3)個節點,操作3次(看自己一眼,下沉2次)
第n-1層,2^(n-2)個節點,操作2次(看自己一眼,下沉1次)
第n層,2^(n-1)個節點,操作1次(看自己一眼,沒子節點,沒法沉)
堆其實就是個完全二叉樹,那麼最底層元素通常佔了一半,於是越底層的交換成本越高,則整體建堆成本越高
例:[2, 3, 1, 4, 6, 5, 9, 7, 8],移動不超過3
解先搞乙個k+1的小根堆,將k+1個元素push進去
當陣列還有元素時,每pop乙個就往裡push乙個
直到小根堆pop空
void
sortedarrdistancelessk
(int
arr,
int k)
priorityqueue
heap =
newpriorityqueue
<
>()
;// 預設為小根堆
int index =0;
for(
; index <= math.
min(arr.length -
1, k)
; index++
)int i =0;
for(
; index < arr.length; i++
, index++
)while
(!heap.
isempty()
)}
堆與堆排序
二叉堆是完全二叉樹或者是近似完全二叉樹。二叉堆滿足二個特性 1 父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值。2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 當父結點的鍵值總是大於或等於任何乙個子節點的鍵值時為最大堆。當父結點的鍵值總是小於或等於任何乙個子節點的鍵值時...
堆與堆排序
堆排序與快速排序,歸併排序一樣都是時間複雜度為o n logn 的幾種常見排序方法。堆排序是就地排序,輔助空間為o 1 它是不穩定的排序方法。排序的穩定性是指如果在排序的序列中,存在前後相同的兩個元素的話,排序前 和排序後他們的相對位置不發生變化 先說說什麼是堆,堆通常是乙個可以被看做一棵樹的陣列物...
堆與堆排序
堆排序與快速排序,歸併排序一樣都是時間複雜度為o n logn 的幾種常見排序方法。學習堆排序前,先講解下什麼是資料結構中的二叉堆。二叉堆是完全二叉樹或者是近似完全二叉樹。二叉堆滿足二個特性 1 父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值。2 每個結點的左子樹和右子樹都是乙個二叉堆...