@@ -9,6 +9,8 @@ export default class Heap {
9
9
* @param {Function } [comparatorFunction]
10
10
*/
11
11
constructor ( comparatorFunction ) {
12
+ // ES6新增,用来检测是否由构造函数调用
13
+ // Heap是个抽象类,不能直接实例,需要通过MinHeap/MaxHeap实例化
12
14
if ( new . target === Heap ) {
13
15
throw new TypeError ( 'Cannot construct Heap instance directly' ) ;
14
16
}
@@ -19,7 +21,7 @@ export default class Heap {
19
21
}
20
22
21
23
/**
22
- * @param {number } parentIndex
24
+ * @param {number } parentIndex 根据Index获取左子节点索引
23
25
* @return {number }
24
26
*/
25
27
getLeftChildIndex ( parentIndex ) {
@@ -35,7 +37,7 @@ export default class Heap {
35
37
}
36
38
37
39
/**
38
- * @param {number } childIndex
40
+ * @param {number } childIndex 根据Index获取父节点索引
39
41
* @return {number }
40
42
*/
41
43
getParentIndex ( childIndex ) {
@@ -98,9 +100,14 @@ export default class Heap {
98
100
const tmp = this . heapContainer [ indexTwo ] ;
99
101
this . heapContainer [ indexTwo ] = this . heapContainer [ indexOne ] ;
100
102
this . heapContainer [ indexOne ] = tmp ;
103
+
104
+ // 可以这样交换
105
+ // [this.heapContainer[indexTwo], this.heapContainer[indexOne]] =
106
+ // [this.heapContainer[indexOne], this.heapContainer[indexTwo]]
101
107
}
102
108
103
109
/**
110
+ * 获取根节点元素
104
111
* @return {* }
105
112
*/
106
113
peek ( ) {
@@ -112,7 +119,8 @@ export default class Heap {
112
119
}
113
120
114
121
/**
115
- * @return {* }
122
+ * Sort关键过程,交换头尾两个元素值,移除头元素,并重新递归构建新Heap
123
+ * @return {* } 返回头元素,此时头元素为一个极值
116
124
*/
117
125
poll ( ) {
118
126
if ( this . heapContainer . length === 0 ) {
@@ -127,6 +135,8 @@ export default class Heap {
127
135
128
136
// Move the last element from the end to the head.
129
137
this . heapContainer [ 0 ] = this . heapContainer . pop ( ) ;
138
+
139
+ // 元素减少后,重新递归构建新Heap
130
140
this . heapifyDown ( ) ;
131
141
132
142
return item ;
@@ -218,14 +228,18 @@ export default class Heap {
218
228
}
219
229
220
230
/**
231
+ * 从下向上重新建堆
221
232
* @param {number } [customStartIndex]
222
233
*/
223
234
heapifyUp ( customStartIndex ) {
235
+ // 在add时,默认从新增元素开始,向上重新建堆,这样可以保证下次ADD前,前面的元素排序
236
+ // 已经基本OK,只需考虑当前元素
224
237
// Take the last element (last in array or the bottom left in a tree)
225
238
// in the heap container and lift it up until it is in the correct
226
239
// order with respect to its parent element.
227
240
let currentIndex = customStartIndex || this . heapContainer . length - 1 ;
228
241
242
+ // 不断的和父元素进行比较,如果大小关系不满足Heap条件,就进行交换
229
243
while (
230
244
this . hasParent ( currentIndex )
231
245
&& ! this . pairIsInCorrectOrder ( this . parent ( currentIndex ) , this . heapContainer [ currentIndex ] )
@@ -236,16 +250,21 @@ export default class Heap {
236
250
}
237
251
238
252
/**
253
+ * 从上向下重新建堆
239
254
* @param {number } [customStartIndex]
240
255
*/
241
256
heapifyDown ( customStartIndex = 0 ) {
242
257
// Compare the parent element to its children and swap parent with the appropriate
243
258
// child (smallest child for MinHeap, largest child for MaxHeap).
244
259
// Do the same for next children after swap.
260
+ // 当使用Heap排序时,顶部元素被赋值为尾元素,此时,需要从顶向下重新建堆
245
261
let currentIndex = customStartIndex ;
246
262
let nextIndex = null ;
247
263
248
264
while ( this . hasLeftChild ( currentIndex ) ) {
265
+ // 与二叉树不同,Heap结构中,左右节点值的关系是不固定的
266
+ // 左节点可能小于右节点,也可能大于右节点,只能保证左右节点和父节点的值大于关系固定
267
+ // 取左右节点中,较大(For MaxHeap)或较小(For MinHeap)的值与父节点进行交换
249
268
if (
250
269
this . hasRightChild ( currentIndex )
251
270
&& this . pairIsInCorrectOrder ( this . rightChild ( currentIndex ) , this . leftChild ( currentIndex ) )
@@ -255,6 +274,8 @@ export default class Heap {
255
274
nextIndex = this . getLeftChildIndex ( currentIndex ) ;
256
275
}
257
276
277
+ // 除去最新的变换节点,比较顶节点,其他节点之间的关系是在之前的过程就调整好的
278
+ // 因此,若最近两个节点关系正确,则可以认为该节点的子树关系是OK的,可以结束
258
279
if ( this . pairIsInCorrectOrder (
259
280
this . heapContainer [ currentIndex ] ,
260
281
this . heapContainer [ nextIndex ] ,
0 commit comments