data-structure-typed 2.0.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -1
- package/COMMANDS.md +17 -0
- package/README.md +11 -11
- package/benchmark/report.html +13 -77
- package/benchmark/report.json +158 -190
- package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
- package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
- package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
- package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
- package/dist/cjs/data-structures/base/linear-base.js +137 -274
- package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +608 -875
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
- package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
- package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
- package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
- package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/cjs/data-structures/graph/map-graph.js +56 -59
- package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
- package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/cjs/data-structures/hash/hash-map.js +270 -457
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
- package/dist/cjs/data-structures/heap/heap.js +340 -349
- package/dist/cjs/data-structures/heap/heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/cjs/data-structures/heap/max-heap.js +11 -66
- package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/cjs/data-structures/heap/min-heap.js +11 -66
- package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
- package/dist/cjs/data-structures/queue/deque.js +309 -348
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
- package/dist/cjs/data-structures/queue/queue.js +265 -248
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
- package/dist/cjs/data-structures/stack/stack.js +181 -125
- package/dist/cjs/data-structures/stack/stack.js.map +1 -1
- package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
- package/dist/cjs/data-structures/trie/trie.js +189 -172
- package/dist/cjs/data-structures/trie/trie.js.map +1 -1
- package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
- package/dist/cjs/interfaces/graph.d.ts +16 -0
- package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
- package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/cjs/types/utils/utils.d.ts +6 -6
- package/dist/cjs/utils/utils.d.ts +110 -49
- package/dist/cjs/utils/utils.js +148 -73
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
- package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
- package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
- package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
- package/dist/esm/data-structures/base/linear-base.js +137 -274
- package/dist/esm/data-structures/base/linear-base.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
- package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/esm/data-structures/binary-tree/binary-tree.js +613 -885
- package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/esm/data-structures/binary-tree/bst.js +507 -487
- package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
- package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
- package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
- package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
- package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/esm/data-structures/graph/directed-graph.js +145 -233
- package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/esm/data-structures/graph/map-graph.js +56 -59
- package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
- package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/esm/data-structures/hash/hash-map.js +270 -457
- package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
- package/dist/esm/data-structures/heap/heap.d.ts +214 -289
- package/dist/esm/data-structures/heap/heap.js +329 -349
- package/dist/esm/data-structures/heap/heap.js.map +1 -1
- package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/esm/data-structures/heap/max-heap.js +11 -66
- package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
- package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/esm/data-structures/heap/min-heap.js +11 -66
- package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
- package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
- package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
- package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/esm/data-structures/queue/deque.d.ts +227 -254
- package/dist/esm/data-structures/queue/deque.js +313 -348
- package/dist/esm/data-structures/queue/deque.js.map +1 -1
- package/dist/esm/data-structures/queue/queue.d.ts +180 -201
- package/dist/esm/data-structures/queue/queue.js +263 -248
- package/dist/esm/data-structures/queue/queue.js.map +1 -1
- package/dist/esm/data-structures/stack/stack.d.ts +124 -102
- package/dist/esm/data-structures/stack/stack.js +181 -125
- package/dist/esm/data-structures/stack/stack.js.map +1 -1
- package/dist/esm/data-structures/trie/trie.d.ts +164 -165
- package/dist/esm/data-structures/trie/trie.js +193 -172
- package/dist/esm/data-structures/trie/trie.js.map +1 -1
- package/dist/esm/interfaces/binary-tree.d.ts +56 -6
- package/dist/esm/interfaces/graph.d.ts +16 -0
- package/dist/esm/types/data-structures/base/base.d.ts +1 -1
- package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/esm/types/utils/utils.d.ts +6 -6
- package/dist/esm/utils/utils.d.ts +110 -49
- package/dist/esm/utils/utils.js +139 -68
- package/dist/esm/utils/utils.js.map +1 -1
- package/dist/umd/data-structure-typed.js +4737 -6525
- package/dist/umd/data-structure-typed.min.js +8 -6
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +3 -4
- package/src/data-structures/base/iterable-element-base.ts +238 -115
- package/src/data-structures/base/iterable-entry-base.ts +96 -120
- package/src/data-structures/base/linear-base.ts +271 -277
- package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
- package/src/data-structures/binary-tree/avl-tree.ts +239 -206
- package/src/data-structures/binary-tree/binary-tree.ts +677 -901
- package/src/data-structures/binary-tree/bst.ts +568 -570
- package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
- package/src/data-structures/binary-tree/tree-counter.ts +199 -218
- package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
- package/src/data-structures/graph/abstract-graph.ts +339 -264
- package/src/data-structures/graph/directed-graph.ts +146 -236
- package/src/data-structures/graph/map-graph.ts +63 -60
- package/src/data-structures/graph/undirected-graph.ts +129 -152
- package/src/data-structures/hash/hash-map.ts +274 -496
- package/src/data-structures/heap/heap.ts +389 -402
- package/src/data-structures/heap/max-heap.ts +12 -76
- package/src/data-structures/heap/min-heap.ts +13 -76
- package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
- package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
- package/src/data-structures/priority-queue/priority-queue.ts +3 -92
- package/src/data-structures/queue/deque.ts +381 -357
- package/src/data-structures/queue/queue.ts +310 -264
- package/src/data-structures/stack/stack.ts +217 -131
- package/src/data-structures/trie/trie.ts +240 -175
- package/src/interfaces/binary-tree.ts +240 -6
- package/src/interfaces/graph.ts +37 -0
- package/src/types/data-structures/base/base.ts +5 -5
- package/src/types/data-structures/graph/abstract-graph.ts +5 -0
- package/src/types/utils/utils.ts +9 -5
- package/src/utils/utils.ts +152 -86
- package/test/integration/index.html +1 -1
- package/test/performance/benchmark-runner.ts +528 -0
- package/test/performance/reportor.mjs +43 -43
- package/test/performance/runner-config.json +39 -0
- package/test/performance/single-suite-runner.ts +69 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
- package/test/unit/data-structures/binary-tree/bst.test.ts +84 -5
- package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
- package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
- package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
- package/test/unit/data-structures/heap/heap.test.ts +14 -21
- package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
- package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
- package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
- package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
- package/test/unit/data-structures/queue/queue.test.ts +4 -5
- package/test/unit/utils/utils.test.ts +0 -1
- package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
- package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +0 -81
|
@@ -6,24 +6,41 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
import { BST, BSTNode } from './bst';
|
|
9
|
+
/**
|
|
10
|
+
* Represents a Node in an AVL (Adelson-Velsky and Landis) Tree.
|
|
11
|
+
* It extends a BSTNode and ensures the 'height' property is maintained.
|
|
12
|
+
*
|
|
13
|
+
* @template K - The type of the key.
|
|
14
|
+
* @template V - The type of the value.
|
|
15
|
+
*/
|
|
9
16
|
export class AVLTreeNode extends BSTNode {
|
|
10
17
|
parent = undefined;
|
|
11
18
|
/**
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* @param
|
|
17
|
-
* have to be provided when creating an instance of the class. If a value is not provided, it will
|
|
18
|
-
* default to `undefined`.
|
|
19
|
+
* Creates an instance of AVLTreeNode.
|
|
20
|
+
* @remarks Time O(1), Space O(1)
|
|
21
|
+
*
|
|
22
|
+
* @param key - The key of the node.
|
|
23
|
+
* @param [value] - The value associated with the key.
|
|
19
24
|
*/
|
|
20
25
|
constructor(key, value) {
|
|
21
26
|
super(key, value);
|
|
22
27
|
}
|
|
23
28
|
_left = undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Gets the left child of the node.
|
|
31
|
+
* @remarks Time O(1), Space O(1)
|
|
32
|
+
*
|
|
33
|
+
* @returns The left child.
|
|
34
|
+
*/
|
|
24
35
|
get left() {
|
|
25
36
|
return this._left;
|
|
26
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Sets the left child of the node and updates its parent reference.
|
|
40
|
+
* @remarks Time O(1), Space O(1)
|
|
41
|
+
*
|
|
42
|
+
* @param v - The node to set as the left child.
|
|
43
|
+
*/
|
|
27
44
|
set left(v) {
|
|
28
45
|
if (v) {
|
|
29
46
|
v.parent = this;
|
|
@@ -31,9 +48,21 @@ export class AVLTreeNode extends BSTNode {
|
|
|
31
48
|
this._left = v;
|
|
32
49
|
}
|
|
33
50
|
_right = undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Gets the right child of the node.
|
|
53
|
+
* @remarks Time O(1), Space O(1)
|
|
54
|
+
*
|
|
55
|
+
* @returns The right child.
|
|
56
|
+
*/
|
|
34
57
|
get right() {
|
|
35
58
|
return this._right;
|
|
36
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Sets the right child of the node and updates its parent reference.
|
|
62
|
+
* @remarks Time O(1), Space O(1)
|
|
63
|
+
*
|
|
64
|
+
* @param v - The node to set as the right child.
|
|
65
|
+
*/
|
|
37
66
|
set right(v) {
|
|
38
67
|
if (v) {
|
|
39
68
|
v.parent = this;
|
|
@@ -42,14 +71,20 @@ export class AVLTreeNode extends BSTNode {
|
|
|
42
71
|
}
|
|
43
72
|
}
|
|
44
73
|
/**
|
|
74
|
+
* Represents a self-balancing AVL (Adelson-Velsky and Landis) Tree.
|
|
75
|
+
* This tree extends BST and performs rotations on add/delete to maintain balance.
|
|
76
|
+
*
|
|
77
|
+
* @template K - The type of the key.
|
|
78
|
+
* @template V - The type of the value.
|
|
79
|
+
* @template R - The type of the raw data object (if using `toEntryFn`).
|
|
80
|
+
*
|
|
45
81
|
* 1. Height-Balanced: Each node's left and right subtrees differ in height by no more than one.
|
|
46
82
|
* 2. Automatic Rebalancing: AVL trees rebalance themselves automatically during insertions and deletions.
|
|
47
83
|
* 3. Rotations for Balancing: Utilizes rotations (single or double) to maintain balance after updates.
|
|
48
84
|
* 4. Order Preservation: Maintains the binary search tree property where left child values are less than the parent, and right child values are greater.
|
|
49
85
|
* 5. Efficient Lookups: Offers O(log n) search time, where 'n' is the number of nodes, due to its balanced nature.
|
|
50
86
|
* 6. Complex Insertions and Deletions: Due to rebalancing, these operations are more complex than in a regular BST.
|
|
51
|
-
* 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes
|
|
52
|
-
* @example
|
|
87
|
+
* 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes.@example
|
|
53
88
|
* // Find elements in a range
|
|
54
89
|
* // In interval queries, AVL trees, with their strictly balanced structure and lower height, offer better query efficiency, making them ideal for frequent and high-performance interval queries. In contrast, Red-Black trees, with lower update costs, are more suitable for scenarios involving frequent insertions and deletions where the requirements for interval queries are less demanding.
|
|
55
90
|
* type Datum = { timestamp: Date; temperature: number };
|
|
@@ -116,107 +151,66 @@ export class AVLTreeNode extends BSTNode {
|
|
|
116
151
|
*/
|
|
117
152
|
export class AVLTree extends BST {
|
|
118
153
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* iterable
|
|
123
|
-
|
|
124
|
-
* used to initialize the AVLTree with key-value pairs or raw data entries. If provided
|
|
125
|
-
* @param [options] - The `options` parameter in the constructor is of type `AVLTreeOptions<K, V,
|
|
126
|
-
* R>`. It is an optional parameter that allows you to specify additional options for configuring the
|
|
127
|
-
* AVL tree. These options could include things like custom comparators, initial capacity, or any
|
|
128
|
-
* other configuration settings specific
|
|
154
|
+
* Creates an instance of AVLTree.
|
|
155
|
+
* @remarks Time O(N log N) (from `addMany` with balanced add). Space O(N).
|
|
156
|
+
*
|
|
157
|
+
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
|
|
158
|
+
* @param [options] - Configuration options for the AVL tree.
|
|
129
159
|
*/
|
|
130
160
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
131
161
|
super([], options);
|
|
162
|
+
// Note: super.addMany is called, which in BST defaults to balanced add.
|
|
132
163
|
if (keysNodesEntriesOrRaws)
|
|
133
164
|
super.addMany(keysNodesEntriesOrRaws);
|
|
134
165
|
}
|
|
135
166
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
167
|
+
* (Protected) Creates a new AVL tree node.
|
|
168
|
+
* @remarks Time O(1), Space O(1)
|
|
138
169
|
*
|
|
139
|
-
*
|
|
140
|
-
* @param
|
|
141
|
-
* created.
|
|
142
|
-
* @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
|
|
143
|
-
* value associated with the key in the node being created.
|
|
144
|
-
* @returns The method is returning a new instance of the AVLTreeNode class, casted as the generic
|
|
145
|
-
* type AVLTreeNode<K, V>.
|
|
170
|
+
* @param key - The key for the new node.
|
|
171
|
+
* @param [value] - The value for the new node.
|
|
172
|
+
* @returns The newly created AVLTreeNode.
|
|
146
173
|
*/
|
|
147
|
-
|
|
174
|
+
_createNode(key, value) {
|
|
148
175
|
return new AVLTreeNode(key, this._isMapMode ? undefined : value);
|
|
149
176
|
}
|
|
150
177
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* The function creates a new AVL tree with the specified options and returns it.
|
|
155
|
-
* @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be
|
|
156
|
-
* passed to the `createTree` function. It is used to customize the behavior of the AVL tree that is
|
|
157
|
-
* being created.
|
|
158
|
-
* @returns a new AVLTree object.
|
|
159
|
-
*/
|
|
160
|
-
createTree(options) {
|
|
161
|
-
return new AVLTree([], {
|
|
162
|
-
iterationType: this.iterationType,
|
|
163
|
-
isMapMode: this._isMapMode,
|
|
164
|
-
specifyComparable: this._specifyComparable,
|
|
165
|
-
toEntryFn: this._toEntryFn,
|
|
166
|
-
isReverse: this._isReverse,
|
|
167
|
-
...options
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Time Complexity: O(1)
|
|
172
|
-
* Space Complexity: O(1)
|
|
178
|
+
* Checks if the given item is an `AVLTreeNode` instance.
|
|
179
|
+
* @remarks Time O(1), Space O(1)
|
|
173
180
|
*
|
|
174
|
-
*
|
|
175
|
-
* @
|
|
176
|
-
* `keyNodeOrEntry` can be of type `R` or `
|
|
177
|
-
K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
|
|
178
|
-
* @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is
|
|
179
|
-
* an instance of the `AVLTreeNode` class.
|
|
181
|
+
* @param keyNodeOrEntry - The item to check.
|
|
182
|
+
* @returns True if it's an AVLTreeNode, false otherwise.
|
|
180
183
|
*/
|
|
181
184
|
isNode(keyNodeOrEntry) {
|
|
182
185
|
return keyNodeOrEntry instanceof AVLTreeNode;
|
|
183
186
|
}
|
|
184
187
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
188
|
+
* Adds a new node to the AVL tree and balances the tree path.
|
|
189
|
+
* @remarks Time O(log N) (O(H) for BST add + O(H) for `_balancePath`). Space O(H) for path/recursion.
|
|
187
190
|
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* @
|
|
191
|
-
* `keyNodeOrEntry` can accept values of type `R`, `
|
|
192
|
-
K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `
|
|
193
|
-
* @param {V} [value] - The `value` parameter is an optional value that you want to associate with
|
|
194
|
-
* the key or node being added to the data structure.
|
|
195
|
-
* @returns The method is returning a boolean value.
|
|
191
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
192
|
+
* @param [value] - The value, if providing just a key.
|
|
193
|
+
* @returns True if the addition was successful, false otherwise.
|
|
196
194
|
*/
|
|
197
195
|
add(keyNodeOrEntry, value) {
|
|
198
196
|
if (keyNodeOrEntry === null)
|
|
199
197
|
return false;
|
|
200
198
|
const inserted = super.add(keyNodeOrEntry, value);
|
|
199
|
+
// If insertion was successful, balance the path from the new node up to the root.
|
|
201
200
|
if (inserted)
|
|
202
201
|
this._balancePath(keyNodeOrEntry);
|
|
203
202
|
return inserted;
|
|
204
203
|
}
|
|
205
204
|
/**
|
|
206
|
-
*
|
|
207
|
-
*
|
|
205
|
+
* Deletes a node from the AVL tree and re-balances the tree.
|
|
206
|
+
* @remarks Time O(log N) (O(H) for BST delete + O(H) for `_balancePath`). Space O(H) for path/recursion.
|
|
208
207
|
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
* @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
|
|
212
|
-
* parameter in the `override delete` method can be one of the following types:
|
|
213
|
-
* @returns The `delete` method is being overridden in this code snippet. It first calls the `delete`
|
|
214
|
-
* method from the superclass (presumably a parent class) with the provided `predicate`, which could
|
|
215
|
-
* be a key, node, entry, or a custom predicate. The result of this deletion operation is stored in
|
|
216
|
-
* `deletedResults`, which is an array of `BinaryTreeDeleteResult` objects.
|
|
208
|
+
* @param keyNodeOrEntry - The node to delete.
|
|
209
|
+
* @returns An array containing deletion results.
|
|
217
210
|
*/
|
|
218
211
|
delete(keyNodeOrEntry) {
|
|
219
212
|
const deletedResults = super.delete(keyNodeOrEntry);
|
|
213
|
+
// After deletion, balance the path from the parent of the *physically deleted* node.
|
|
220
214
|
for (const { needBalanced } of deletedResults) {
|
|
221
215
|
if (needBalanced) {
|
|
222
216
|
this._balancePath(needBalanced);
|
|
@@ -225,71 +219,108 @@ export class AVLTree extends BST {
|
|
|
225
219
|
return deletedResults;
|
|
226
220
|
}
|
|
227
221
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
222
|
+
* Rebuilds the tree to be perfectly balanced.
|
|
223
|
+
* @remarks AVL trees are already height-balanced, but this makes them *perfectly* balanced (minimal height and all leaves at N or N-1).
|
|
224
|
+
* Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
|
|
230
225
|
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
226
|
+
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
227
|
+
* @returns True if successful, false if the tree was empty.
|
|
228
|
+
*/
|
|
229
|
+
perfectlyBalance(iterationType = this.iterationType) {
|
|
230
|
+
const nodes = this.dfs(node => node, 'IN', false, this._root, iterationType);
|
|
231
|
+
const n = nodes.length;
|
|
232
|
+
if (n === 0)
|
|
233
|
+
return false;
|
|
234
|
+
this._clearNodes();
|
|
235
|
+
// Build balanced tree from sorted array
|
|
236
|
+
const build = (l, r, parent) => {
|
|
237
|
+
if (l > r)
|
|
238
|
+
return undefined;
|
|
239
|
+
const m = l + ((r - l) >> 1);
|
|
240
|
+
const root = nodes[m];
|
|
241
|
+
root.left = build(l, m - 1, root);
|
|
242
|
+
root.right = build(m + 1, r, root);
|
|
243
|
+
root.parent = parent;
|
|
244
|
+
// Update height during the build
|
|
245
|
+
const lh = root.left ? root.left.height : -1;
|
|
246
|
+
const rh = root.right ? root.right.height : -1;
|
|
247
|
+
root.height = Math.max(lh, rh) + 1;
|
|
248
|
+
return root;
|
|
249
|
+
};
|
|
250
|
+
const newRoot = build(0, n - 1, undefined);
|
|
251
|
+
this._setRoot(newRoot);
|
|
252
|
+
this._size = n;
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Creates a new AVLTree by mapping each [key, value] pair.
|
|
257
|
+
* @remarks Time O(N log N) (O(N) iteration + O(log M) `add` for each item into the new tree). Space O(N) for the new tree.
|
|
258
|
+
*
|
|
259
|
+
* @template MK - New key type.
|
|
260
|
+
* @template MV - New value type.
|
|
261
|
+
* @template MR - New raw type.
|
|
262
|
+
* @param callback - A function to map each [key, value] pair.
|
|
263
|
+
* @param [options] - Options for the new AVLTree.
|
|
264
|
+
* @param [thisArg] - `this` context for the callback.
|
|
265
|
+
* @returns A new, mapped AVLTree.
|
|
246
266
|
*/
|
|
247
267
|
map(callback, options, thisArg) {
|
|
248
|
-
const
|
|
268
|
+
const out = this._createLike([], options);
|
|
249
269
|
let index = 0;
|
|
270
|
+
// Iterates in-order
|
|
250
271
|
for (const [key, value] of this) {
|
|
251
|
-
|
|
272
|
+
// `add` on the new tree will be O(log N) and will self-balance.
|
|
273
|
+
out.add(callback.call(thisArg, key, value, index++, this));
|
|
252
274
|
}
|
|
253
|
-
return
|
|
275
|
+
return out;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* (Protected) Creates a new, empty instance of the same AVLTree constructor.
|
|
279
|
+
* @remarks Time O(1)
|
|
280
|
+
*
|
|
281
|
+
* @template TK, TV, TR - Generic types for the new instance.
|
|
282
|
+
* @param [options] - Options for the new tree.
|
|
283
|
+
* @returns A new, empty tree.
|
|
284
|
+
*/
|
|
285
|
+
_createInstance(options) {
|
|
286
|
+
const Ctor = this.constructor;
|
|
287
|
+
return new Ctor([], { ...this._snapshotOptions(), ...(options ?? {}) });
|
|
254
288
|
}
|
|
255
289
|
/**
|
|
256
|
-
*
|
|
257
|
-
*
|
|
290
|
+
* (Protected) Creates a new instance of the same AVLTree constructor, potentially with different generic types.
|
|
291
|
+
* @remarks Time O(N log N) (from constructor) due to processing the iterable.
|
|
258
292
|
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
* @
|
|
293
|
+
* @template TK, TV, TR - Generic types for the new instance.
|
|
294
|
+
* @param [iter=[]] - An iterable to populate the new tree.
|
|
295
|
+
* @param [options] - Options for the new tree.
|
|
296
|
+
* @returns A new AVLTree.
|
|
262
297
|
*/
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
this.
|
|
266
|
-
return cloned;
|
|
298
|
+
_createLike(iter = [], options) {
|
|
299
|
+
const Ctor = this.constructor;
|
|
300
|
+
return new Ctor(iter, { ...this._snapshotOptions(), ...(options ?? {}) });
|
|
267
301
|
}
|
|
268
302
|
/**
|
|
269
|
-
*
|
|
270
|
-
*
|
|
303
|
+
* (Protected) Swaps properties of two nodes, including height.
|
|
304
|
+
* @remarks Time O(H) (due to `ensureNode`), but O(1) if nodes are passed directly.
|
|
271
305
|
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
* @
|
|
275
|
-
* object (`AVLTreeNode<K, V>`) or a key-value pair (`R`) that is being swapped with another node.
|
|
276
|
-
* @param {BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>} destNode - The `destNode` parameter is either an instance of
|
|
277
|
-
* `R` or an instance of `BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>`.
|
|
278
|
-
* @returns The method is returning the `destNodeEnsured` object if both `srcNodeEnsured` and
|
|
279
|
-
* `destNodeEnsured` are truthy. Otherwise, it returns `undefined`.
|
|
306
|
+
* @param srcNode - The source node.
|
|
307
|
+
* @param destNode - The destination node.
|
|
308
|
+
* @returns The `destNode` (now holding `srcNode`'s properties).
|
|
280
309
|
*/
|
|
281
310
|
_swapProperties(srcNode, destNode) {
|
|
282
311
|
const srcNodeEnsured = this.ensureNode(srcNode);
|
|
283
312
|
const destNodeEnsured = this.ensureNode(destNode);
|
|
284
313
|
if (srcNodeEnsured && destNodeEnsured) {
|
|
285
314
|
const { key, value, height } = destNodeEnsured;
|
|
286
|
-
const tempNode = this.
|
|
315
|
+
const tempNode = this._createNode(key, value);
|
|
287
316
|
if (tempNode) {
|
|
288
317
|
tempNode.height = height;
|
|
318
|
+
// Copy src to dest
|
|
289
319
|
destNodeEnsured.key = srcNodeEnsured.key;
|
|
290
320
|
if (!this._isMapMode)
|
|
291
321
|
destNodeEnsured.value = srcNodeEnsured.value;
|
|
292
322
|
destNodeEnsured.height = srcNodeEnsured.height;
|
|
323
|
+
// Copy temp (original dest) to src
|
|
293
324
|
srcNodeEnsured.key = tempNode.key;
|
|
294
325
|
if (!this._isMapMode)
|
|
295
326
|
srcNodeEnsured.value = tempNode.value;
|
|
@@ -300,55 +331,37 @@ export class AVLTree extends BST {
|
|
|
300
331
|
return undefined;
|
|
301
332
|
}
|
|
302
333
|
/**
|
|
303
|
-
*
|
|
304
|
-
*
|
|
334
|
+
* (Protected) Calculates the balance factor (height(right) - height(left)).
|
|
335
|
+
* @remarks Time O(1) (assumes heights are stored).
|
|
305
336
|
*
|
|
306
|
-
*
|
|
307
|
-
* @
|
|
308
|
-
* binary tree data structure.
|
|
309
|
-
* @returns the balance factor of a given node. The balance factor is calculated by subtracting the
|
|
310
|
-
* height of the left subtree from the height of the right subtree.
|
|
337
|
+
* @param node - The node to check.
|
|
338
|
+
* @returns The balance factor (positive if right-heavy, negative if left-heavy).
|
|
311
339
|
*/
|
|
312
340
|
_balanceFactor(node) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
else if (!node.left)
|
|
317
|
-
// node has no left subtree
|
|
318
|
-
return +node.height;
|
|
319
|
-
else
|
|
320
|
-
return node.right.height - node.left.height;
|
|
341
|
+
const left = node.left ? node.left.height : -1;
|
|
342
|
+
const right = node.right ? node.right.height : -1;
|
|
343
|
+
return right - left;
|
|
321
344
|
}
|
|
322
345
|
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
346
|
+
* (Protected) Recalculates and updates the height of a node based on its children's heights.
|
|
347
|
+
* @remarks Time O(1) (assumes children's heights are correct).
|
|
325
348
|
*
|
|
326
|
-
*
|
|
327
|
-
* right children.
|
|
328
|
-
* @param {AVLTreeNode<K, V>} node - The parameter "node" represents a node in a binary tree data structure.
|
|
349
|
+
* @param node - The node to update.
|
|
329
350
|
*/
|
|
330
351
|
_updateHeight(node) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const rightHeight = node.right ? node.right.height : 0;
|
|
335
|
-
node.height = 1 + rightHeight;
|
|
336
|
-
}
|
|
337
|
-
else if (!node.right)
|
|
338
|
-
node.height = 1 + node.left.height;
|
|
339
|
-
else
|
|
340
|
-
node.height = 1 + Math.max(node.right.height, node.left.height);
|
|
352
|
+
const leftHeight = node.left ? node.left.height : -1;
|
|
353
|
+
const rightHeight = node.right ? node.right.height : -1;
|
|
354
|
+
node.height = 1 + Math.max(leftHeight, rightHeight);
|
|
341
355
|
}
|
|
342
356
|
/**
|
|
343
|
-
*
|
|
344
|
-
*
|
|
357
|
+
* (Protected) Performs a Left-Left (LL) rotation (a single right rotation).
|
|
358
|
+
* @remarks Time O(1), Space O(1)
|
|
345
359
|
*
|
|
346
|
-
*
|
|
347
|
-
* @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
|
|
360
|
+
* @param A - The unbalanced node (root of the unbalanced subtree).
|
|
348
361
|
*/
|
|
349
362
|
_balanceLL(A) {
|
|
350
363
|
const parentOfA = A.parent;
|
|
351
|
-
const B = A.left;
|
|
364
|
+
const B = A.left; // The left child
|
|
352
365
|
if (B !== null)
|
|
353
366
|
A.parent = B;
|
|
354
367
|
if (B && B.right) {
|
|
@@ -356,6 +369,7 @@ export class AVLTree extends BST {
|
|
|
356
369
|
}
|
|
357
370
|
if (B)
|
|
358
371
|
B.parent = parentOfA;
|
|
372
|
+
// Update parent's child pointer
|
|
359
373
|
if (A === this.root) {
|
|
360
374
|
if (B)
|
|
361
375
|
this._setRoot(B);
|
|
@@ -369,6 +383,7 @@ export class AVLTree extends BST {
|
|
|
369
383
|
parentOfA.right = B;
|
|
370
384
|
}
|
|
371
385
|
}
|
|
386
|
+
// Perform rotation
|
|
372
387
|
if (B) {
|
|
373
388
|
A.left = B.right;
|
|
374
389
|
B.right = A;
|
|
@@ -378,18 +393,17 @@ export class AVLTree extends BST {
|
|
|
378
393
|
this._updateHeight(B);
|
|
379
394
|
}
|
|
380
395
|
/**
|
|
381
|
-
*
|
|
382
|
-
*
|
|
396
|
+
* (Protected) Performs a Left-Right (LR) double rotation.
|
|
397
|
+
* @remarks Time O(1), Space O(1)
|
|
383
398
|
*
|
|
384
|
-
*
|
|
385
|
-
* @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
|
|
399
|
+
* @param A - The unbalanced node (root of the unbalanced subtree).
|
|
386
400
|
*/
|
|
387
401
|
_balanceLR(A) {
|
|
388
402
|
const parentOfA = A.parent;
|
|
389
403
|
const B = A.left;
|
|
390
404
|
let C = undefined;
|
|
391
405
|
if (B) {
|
|
392
|
-
C = B.right;
|
|
406
|
+
C = B.right; // The "middle" node
|
|
393
407
|
}
|
|
394
408
|
if (A && C !== null)
|
|
395
409
|
A.parent = C;
|
|
@@ -405,6 +419,7 @@ export class AVLTree extends BST {
|
|
|
405
419
|
}
|
|
406
420
|
C.parent = parentOfA;
|
|
407
421
|
}
|
|
422
|
+
// Update parent's child pointer
|
|
408
423
|
if (A === this.root) {
|
|
409
424
|
if (C)
|
|
410
425
|
this._setRoot(C);
|
|
@@ -419,6 +434,7 @@ export class AVLTree extends BST {
|
|
|
419
434
|
}
|
|
420
435
|
}
|
|
421
436
|
}
|
|
437
|
+
// Perform rotation
|
|
422
438
|
if (C) {
|
|
423
439
|
A.left = C.right;
|
|
424
440
|
if (B)
|
|
@@ -433,15 +449,14 @@ export class AVLTree extends BST {
|
|
|
433
449
|
this._updateHeight(C);
|
|
434
450
|
}
|
|
435
451
|
/**
|
|
436
|
-
*
|
|
437
|
-
*
|
|
452
|
+
* (Protected) Performs a Right-Right (RR) rotation (a single left rotation).
|
|
453
|
+
* @remarks Time O(1), Space O(1)
|
|
438
454
|
*
|
|
439
|
-
*
|
|
440
|
-
* @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
|
|
455
|
+
* @param A - The unbalanced node (root of the unbalanced subtree).
|
|
441
456
|
*/
|
|
442
457
|
_balanceRR(A) {
|
|
443
458
|
const parentOfA = A.parent;
|
|
444
|
-
const B = A.right;
|
|
459
|
+
const B = A.right; // The right child
|
|
445
460
|
if (B !== null)
|
|
446
461
|
A.parent = B;
|
|
447
462
|
if (B) {
|
|
@@ -450,6 +465,7 @@ export class AVLTree extends BST {
|
|
|
450
465
|
}
|
|
451
466
|
B.parent = parentOfA;
|
|
452
467
|
}
|
|
468
|
+
// Update parent's child pointer
|
|
453
469
|
if (A === this.root) {
|
|
454
470
|
if (B)
|
|
455
471
|
this._setRoot(B);
|
|
@@ -464,6 +480,7 @@ export class AVLTree extends BST {
|
|
|
464
480
|
}
|
|
465
481
|
}
|
|
466
482
|
}
|
|
483
|
+
// Perform rotation
|
|
467
484
|
if (B) {
|
|
468
485
|
A.right = B.left;
|
|
469
486
|
B.left = A;
|
|
@@ -473,18 +490,17 @@ export class AVLTree extends BST {
|
|
|
473
490
|
this._updateHeight(B);
|
|
474
491
|
}
|
|
475
492
|
/**
|
|
476
|
-
*
|
|
477
|
-
*
|
|
493
|
+
* (Protected) Performs a Right-Left (RL) double rotation.
|
|
494
|
+
* @remarks Time O(1), Space O(1)
|
|
478
495
|
*
|
|
479
|
-
*
|
|
480
|
-
* @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.
|
|
496
|
+
* @param A - The unbalanced node (root of the unbalanced subtree).
|
|
481
497
|
*/
|
|
482
498
|
_balanceRL(A) {
|
|
483
499
|
const parentOfA = A.parent;
|
|
484
500
|
const B = A.right;
|
|
485
501
|
let C = undefined;
|
|
486
502
|
if (B) {
|
|
487
|
-
C = B.left;
|
|
503
|
+
C = B.left; // The "middle" node
|
|
488
504
|
}
|
|
489
505
|
if (C !== null)
|
|
490
506
|
A.parent = C;
|
|
@@ -500,6 +516,7 @@ export class AVLTree extends BST {
|
|
|
500
516
|
}
|
|
501
517
|
C.parent = parentOfA;
|
|
502
518
|
}
|
|
519
|
+
// Update parent's child pointer
|
|
503
520
|
if (A === this.root) {
|
|
504
521
|
if (C)
|
|
505
522
|
this._setRoot(C);
|
|
@@ -514,6 +531,7 @@ export class AVLTree extends BST {
|
|
|
514
531
|
}
|
|
515
532
|
}
|
|
516
533
|
}
|
|
534
|
+
// Perform rotation
|
|
517
535
|
if (C)
|
|
518
536
|
A.right = C.left;
|
|
519
537
|
if (B && C)
|
|
@@ -529,71 +547,59 @@ export class AVLTree extends BST {
|
|
|
529
547
|
this._updateHeight(C);
|
|
530
548
|
}
|
|
531
549
|
/**
|
|
532
|
-
*
|
|
533
|
-
*
|
|
550
|
+
* (Protected) Traverses up the tree from the specified node, updating heights and performing rotations as needed.
|
|
551
|
+
* @remarks Time O(log N) (O(H)), as it traverses the path to root. Space O(H) for the path array.
|
|
534
552
|
*
|
|
535
|
-
*
|
|
536
|
-
* to restore balance in an AVL tree after inserting a node.
|
|
537
|
-
* @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } node - The `node` parameter can be of type `R` or
|
|
538
|
-
* `
|
|
539
|
-
K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
|
|
553
|
+
* @param node - The node to start balancing from (e.g., the newly inserted node or parent of the deleted node).
|
|
540
554
|
*/
|
|
541
555
|
_balancePath(node) {
|
|
556
|
+
// Get the path from the node to the root.
|
|
542
557
|
node = this.ensureNode(node);
|
|
543
|
-
const path = this.getPathToRoot(node, node => node, false);
|
|
558
|
+
const path = this.getPathToRoot(node, node => node, false);
|
|
559
|
+
// Iterate up the path (from node to root)
|
|
544
560
|
for (let i = 0; i < path.length; i++) {
|
|
545
|
-
// second O(log n)
|
|
546
561
|
const A = path[i];
|
|
547
562
|
if (A) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
switch (this._balanceFactor(A) // second O(1)
|
|
553
|
-
) {
|
|
554
|
-
case -2:
|
|
563
|
+
this._updateHeight(A);
|
|
564
|
+
// Check the balance factor
|
|
565
|
+
switch (this._balanceFactor(A)) {
|
|
566
|
+
case -2: // Left-heavy
|
|
555
567
|
if (A && A.left) {
|
|
556
568
|
if (this._balanceFactor(A.left) <= 0) {
|
|
557
|
-
//
|
|
558
|
-
// Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
|
|
569
|
+
// Left-Left case
|
|
559
570
|
this._balanceLL(A);
|
|
560
571
|
}
|
|
561
572
|
else {
|
|
562
|
-
// Left-Right
|
|
573
|
+
// Left-Right case
|
|
563
574
|
this._balanceLR(A);
|
|
564
575
|
}
|
|
565
576
|
}
|
|
566
577
|
break;
|
|
567
|
-
case +2:
|
|
578
|
+
case +2: // Right-heavy
|
|
568
579
|
if (A && A.right) {
|
|
569
580
|
if (this._balanceFactor(A.right) >= 0) {
|
|
570
|
-
// Right
|
|
581
|
+
// Right-Right case
|
|
571
582
|
this._balanceRR(A);
|
|
572
583
|
}
|
|
573
584
|
else {
|
|
574
|
-
// Right-Left
|
|
585
|
+
// Right-Left case
|
|
575
586
|
this._balanceRL(A);
|
|
576
587
|
}
|
|
577
588
|
}
|
|
578
589
|
}
|
|
579
|
-
// TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.
|
|
580
590
|
}
|
|
581
591
|
}
|
|
582
592
|
}
|
|
583
593
|
/**
|
|
584
|
-
*
|
|
585
|
-
*
|
|
594
|
+
* (Protected) Replaces a node, ensuring height is copied.
|
|
595
|
+
* @remarks Time O(1)
|
|
586
596
|
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
* @
|
|
590
|
-
* the data structure.
|
|
591
|
-
* @param {AVLTreeNode<K, V>} newNode - The `newNode` parameter is the new node that will replace the `oldNode` in
|
|
592
|
-
* the data structure.
|
|
593
|
-
* @returns The method is returning the result of calling the `_replaceNode` method from the
|
|
594
|
-
* superclass, with the `oldNode` and `newNode` as arguments.
|
|
597
|
+
* @param oldNode - The node to be replaced.
|
|
598
|
+
* @param newNode - The node to insert.
|
|
599
|
+
* @returns The `newNode`.
|
|
595
600
|
*/
|
|
596
601
|
_replaceNode(oldNode, newNode) {
|
|
602
|
+
// When replacing a node (e.g., on duplicate key), preserve the height.
|
|
597
603
|
newNode.height = oldNode.height;
|
|
598
604
|
return super._replaceNode(oldNode, newNode);
|
|
599
605
|
}
|