Skip to content

Commit f4bdee2

Browse files
author
YuChengKai
committed
heap
1 parent a7f6656 commit f4bdee2

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

CSS/css-zh.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,4 @@ div {
4040
- em:相对于自身的 `font-size` 大小
4141
- rem:相对于根元素的 `font-size` 大小
4242
- vw:相对于 viewport 的宽度
43-
- vh:相对于 viewport 的高度
44-
43+
- vh:相对于 viewport 的高度

DataStruct/dataStruct-zh.md

+76
Original file line numberDiff line numberDiff line change
@@ -716,5 +716,81 @@ class DisjointSet {
716716

717717
#
718718

719+
## 概念
720+
721+
堆通常是一个可以被看做一棵树的数组对象。
722+
723+
堆的实现通过构造**二叉堆**,实为二叉树的一种。这种数据结构具有以下性质。
724+
725+
- 任意节点小于(或大于)它的所有子节点
726+
- 堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层从左到右填入。
727+
728+
将根节点最大的堆叫做**最大堆****大根堆**,根节点最小的堆叫做**最小堆****小根堆**
729+
730+
## 实现大根堆
731+
732+
堆的每个节点的左边子节点索引是 `i * 2 + 1`,右边是 `i * 2 + 2`,父节点是 `(i - 1) /2`
733+
734+
堆有两个核心的操作,分别是 `shiftUp``shiftDown` 。前者用于添加元素,后者用于删除根节点。
735+
736+
`shiftUp` 的核心思路是一路将节点与父节点对比大小,如果比父节点大,就和父节点交换位置。
737+
738+
`shiftDown` 的核心思路是先将根节点和末尾交换位置,然后移除末尾元素。接下来循环判断父节点和两个子节点的大小,如果子节点大,就把最大的子节点和父节点交换。
739+
740+
```js
741+
class MaxHeap {
742+
constructor() {
743+
this.heap = []
744+
}
745+
size() {
746+
return this.heap.length
747+
}
748+
empty() {
749+
return this.size() == 0
750+
}
751+
add(item) {
752+
this.heap.push(item)
753+
this._shiftUp(this.size() - 1)
754+
}
755+
removeMax() {
756+
this._shiftDown(0)
757+
}
758+
getParentIndex(k) {
759+
return parseInt((k - 1) / 2)
760+
}
761+
getLeftIndex(k) {
762+
return k * 2 + 1
763+
}
764+
_shiftUp(k) {
765+
// 如果当前节点比父节点大,就交换
766+
while (this.heap[k] > this.heap[this.getParentIndex(k)]) {
767+
this._swap(k, this.getParentIndex(k))
768+
// 将索引变成父节点
769+
k = this.getParentIndex(k)
770+
}
771+
}
772+
_shiftDown(k) {
773+
// 交换首位并删除末尾
774+
this._swap(k, this.size() - 1)
775+
this.heap.splice(this.size() - 1, 1)
776+
// 判断节点是否有左孩子,因为二叉堆的特性,有右必有左
777+
while (this.getLeftIndex(k) < this.size()) {
778+
let j = this.getLeftIndex(k)
779+
// 判断是否有右孩子,并且右孩子是否大于左孩子
780+
if (j + 1 < this.size() && this.heap[j + 1] > this.heap[j]) j++
781+
// 判断父节点是否已经比子节点都大
782+
if (this.heap[k] >= this.heap[j]) break
783+
this._swap(k, j)
784+
k = j
785+
}
786+
}
787+
_swap(left, right) {
788+
let rightValue = this.heap[right]
789+
this.heap[right] = this.heap[left]
790+
this.heap[left] = rightValue
791+
}
792+
}
793+
```
794+
719795
# 哈希
720796

0 commit comments

Comments
 (0)