這是我參與8月更文挑戰的第八天,活動詳情查看:8月更文挑戰」前端
今天這一章就來介紹一下堆這種數據結構。markdown
堆是一種特殊的徹底二叉樹
。數據結構
全部的節點都大於等於(最大堆)或小於等於(最小堆)它的子節點。app
JS
中一般用數組表示堆。以前講到的二叉樹都是用 Object
表示的,這裏怎麼能夠用數組呢?post
如圖:ui
咱們能夠把廣度優先遍歷的順序做爲數組下標,遍歷的值做爲數組的值,這樣咱們就能夠表示一個堆了。this
左側子節點的位置是 2 * index + 1 。url
右側子節點的位置是 2 * index + 2 。spa
父節點位置是 (index - 1)/ 2 。
堆能高效、快速地找出最大值和最小值,時間複雜度:O(1)。
找出第 K 個最大(小)元素。
構建一個最小堆,並將元素依次插入堆中。
當堆的容量超過 K, 就刪除堆頂。
插入結束後,堆頂就是第 K 個最大元素。
class MinHeap {
constructor() {
this.heap = []
}
}
複製代碼
主要方法:插入、刪除堆頂、獲取堆頂、獲取堆大小。
將值插入堆的底部,即數組的尾部。
而後上移:將這個值和它的父節點進行交換,直到父節點小於等於這個插入的值。
大小爲 K 的堆中插入元素的時間複雜度爲 O(logk)
class MinHeap {
constructor() {
this.heap = []
}
swap(i1, i2) {
const temp = this.heap[i1]
this.heap[i1] = this.heap[i2]
this.heap[i2] = temp
}
getParentIndex(i) {
// 以下寫,顯得比較臃腫
// Math.floor((i - 1) / 2)
// 能夠經過二進制向前移一位的操做
// 實現除2取整的
return (i - 1) >> 1
}
shiftUp(index) {
if (index === 0) return
const parentIndex = this.getParentIndex(index)
if (this.heap[parentIndex] > this.heap[index]) {
this.swap(parentIndex, index)
this.shiftUp(parentIndex)
}
}
insert(value) {
this.heap.push(value)
this.shiftUp(this.heap.length - 1)
}
}
const h = new MinHeap()
h.insert(3)
h.insert(2)
h.insert(1)
console.log(h);
// MinHeap { heap: [ 1, 3, 2 ] }
複製代碼
用數組尾部元素替換堆頂(直接刪除堆頂會破壞堆結構)。
而後下移: 將新堆頂和它的子節點進行交換,直到子節點大於等於這個新堆頂。
大小爲 K 的堆中刪除堆頂的時間複雜度爲 O(logk)。
class MinHeap {
constructor() {
this.heap = []
}
swap(i1, i2) {
const temp = this.heap[i1]
this.heap[i1] = this.heap[i2]
this.heap[i2] = temp
}
getLeftIndex(i) {
return i * 2 + 1
}
getRightIndex(i) {
return i * 2 + 2
}
shiftDown(index) {
const leftIndex = this.getLeftIndex(index)
const rightIndex = this.getRightIndex(index)
if (this.heap[leftIndex] < this.heap[index]) {
this.swap(leftIndex, rightIndex)
this.shiftDown(leftIndex)
}
if (this.heap[rightIndex] < this.heap[index]) {
this.swap(rightIndex, rightIndex)
this.shiftDown(rightIndex)
}
}
pop() {
this.heap[0] = this.heap.pop()
this.shiftDown(0)
}
}
const h = new MinHeap()
h.insert(3)
h.insert(2)
h.insert(1)
h.pop()
console.log(h)
// MinHeap { heap: [ 2, 3 ] }
複製代碼
獲取堆頂:返回數組的頭部。
獲取堆的大小:返回數組的長度。
class MinHeap {
constructor() {
this.heap = []
}
peek() {
return this.heap[0]
}
size() {
return this.heap.length
}
}
const h = new MinHeap()
h.insert(3)
h.insert(2)
h.insert(1)
console.log(h);
// 1 3
複製代碼
End~~~