@@ -716,5 +716,81 @@ class DisjointSet {
716
716
717
717
# 堆
718
718
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
+
719
795
# 哈希
720
796
0 commit comments