red-black-tree-typed 1.53.7 → 1.54.2
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/LICENSE +2 -2
- package/README.md +52 -0
- package/dist/common/index.js +5 -0
- package/dist/data-structures/base/iterable-entry-base.js +4 -4
- package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +213 -0
- package/dist/data-structures/binary-tree/avl-tree-counter.js +407 -0
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +71 -170
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +133 -328
- package/dist/data-structures/binary-tree/avl-tree.d.ts +103 -69
- package/dist/data-structures/binary-tree/avl-tree.js +130 -70
- package/dist/data-structures/binary-tree/binary-indexed-tree.d.ts +3 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +3 -0
- package/dist/data-structures/binary-tree/binary-tree.d.ts +268 -202
- package/dist/data-structures/binary-tree/binary-tree.js +311 -263
- package/dist/data-structures/binary-tree/bst.d.ts +193 -139
- package/dist/data-structures/binary-tree/bst.js +248 -164
- package/dist/data-structures/binary-tree/index.d.ts +3 -1
- package/dist/data-structures/binary-tree/index.js +3 -1
- package/dist/data-structures/binary-tree/red-black-tree.d.ts +286 -0
- package/dist/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +176 -107
- package/dist/data-structures/binary-tree/tree-counter.d.ts +212 -0
- package/dist/data-structures/binary-tree/tree-counter.js +444 -0
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +78 -170
- package/dist/data-structures/binary-tree/tree-multi-map.js +145 -367
- package/dist/data-structures/graph/abstract-graph.js +2 -2
- package/dist/data-structures/graph/directed-graph.d.ts +3 -0
- package/dist/data-structures/graph/directed-graph.js +3 -0
- package/dist/data-structures/graph/map-graph.d.ts +3 -0
- package/dist/data-structures/graph/map-graph.js +3 -0
- package/dist/data-structures/graph/undirected-graph.d.ts +3 -0
- package/dist/data-structures/graph/undirected-graph.js +3 -0
- package/dist/data-structures/hash/hash-map.d.ts +31 -1
- package/dist/data-structures/hash/hash-map.js +35 -5
- package/dist/data-structures/heap/heap.d.ts +20 -3
- package/dist/data-structures/heap/heap.js +31 -11
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +46 -11
- package/dist/data-structures/linked-list/doubly-linked-list.js +68 -21
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +47 -11
- package/dist/data-structures/linked-list/singly-linked-list.js +73 -26
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +3 -0
- package/dist/data-structures/linked-list/skip-linked-list.js +3 -0
- package/dist/data-structures/matrix/matrix.d.ts +3 -0
- package/dist/data-structures/matrix/matrix.js +3 -0
- package/dist/data-structures/matrix/navigator.d.ts +3 -0
- package/dist/data-structures/matrix/navigator.js +3 -0
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +3 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +3 -0
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +3 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +3 -0
- package/dist/data-structures/queue/deque.d.ts +37 -8
- package/dist/data-structures/queue/deque.js +73 -29
- package/dist/data-structures/queue/queue.d.ts +41 -1
- package/dist/data-structures/queue/queue.js +51 -9
- package/dist/data-structures/stack/stack.d.ts +27 -10
- package/dist/data-structures/stack/stack.js +39 -20
- package/dist/data-structures/trie/trie.d.ts +8 -7
- package/dist/data-structures/trie/trie.js +8 -7
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/interfaces/binary-tree.d.ts +8 -8
- package/dist/types/data-structures/base/base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -4
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +0 -3
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +0 -3
- package/dist/types/data-structures/binary-tree/bst.d.ts +4 -4
- package/dist/types/data-structures/binary-tree/index.d.ts +3 -1
- package/dist/types/data-structures/binary-tree/index.js +3 -1
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +3 -0
- package/dist/types/data-structures/binary-tree/red-black-tree.js +2 -0
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/tree-counter.js +2 -0
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -5
- package/package.json +3 -3
- package/src/common/index.ts +7 -1
- package/src/data-structures/base/iterable-entry-base.ts +4 -4
- package/src/data-structures/binary-tree/avl-tree-counter.ts +463 -0
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +151 -370
- package/src/data-structures/binary-tree/avl-tree.ts +162 -105
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-tree.ts +488 -416
- package/src/data-structures/binary-tree/bst.ts +326 -251
- package/src/data-structures/binary-tree/index.ts +3 -1
- package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +219 -145
- package/src/data-structures/binary-tree/tree-counter.ts +504 -0
- package/src/data-structures/binary-tree/tree-multi-map.ts +159 -401
- package/src/data-structures/graph/abstract-graph.ts +2 -2
- package/src/data-structures/graph/directed-graph.ts +3 -0
- package/src/data-structures/graph/map-graph.ts +3 -0
- package/src/data-structures/graph/undirected-graph.ts +3 -0
- package/src/data-structures/hash/hash-map.ts +37 -7
- package/src/data-structures/heap/heap.ts +33 -10
- package/src/data-structures/linked-list/doubly-linked-list.ts +75 -21
- package/src/data-structures/linked-list/singly-linked-list.ts +80 -27
- package/src/data-structures/linked-list/skip-linked-list.ts +3 -0
- package/src/data-structures/matrix/matrix.ts +3 -0
- package/src/data-structures/matrix/navigator.ts +3 -0
- package/src/data-structures/priority-queue/max-priority-queue.ts +3 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +3 -0
- package/src/data-structures/queue/deque.ts +72 -28
- package/src/data-structures/queue/queue.ts +50 -7
- package/src/data-structures/stack/stack.ts +39 -20
- package/src/data-structures/trie/trie.ts +8 -7
- package/src/index.ts +4 -4
- package/src/interfaces/binary-tree.ts +10 -21
- package/src/types/data-structures/base/base.ts +1 -1
- package/src/types/data-structures/binary-tree/avl-tree-counter.ts +3 -0
- package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +1 -6
- package/src/types/data-structures/binary-tree/avl-tree.ts +0 -5
- package/src/types/data-structures/binary-tree/binary-tree.ts +0 -5
- package/src/types/data-structures/binary-tree/bst.ts +6 -6
- package/src/types/data-structures/binary-tree/index.ts +3 -1
- package/src/types/data-structures/binary-tree/red-black-tree.ts +5 -0
- package/src/types/data-structures/binary-tree/tree-counter.ts +3 -0
- package/src/types/data-structures/binary-tree/tree-multi-map.ts +2 -7
- package/dist/data-structures/binary-tree/rb-tree.d.ts +0 -209
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +0 -6
- package/src/types/data-structures/binary-tree/rb-tree.ts +0 -10
- /package/dist/types/data-structures/binary-tree/{rb-tree.js → avl-tree-counter.js} +0 -0
|
@@ -6,10 +6,8 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import type {
|
|
10
10
|
BinaryTreeDeleteResult,
|
|
11
|
-
BinaryTreeNested,
|
|
12
|
-
BinaryTreeNodeNested,
|
|
13
11
|
BinaryTreeOptions,
|
|
14
12
|
BinaryTreePrintOptions,
|
|
15
13
|
BTNEntry,
|
|
@@ -23,6 +21,7 @@ import {
|
|
|
23
21
|
NodeDisplayLayout,
|
|
24
22
|
NodePredicate,
|
|
25
23
|
OptNodeOrNull,
|
|
24
|
+
RBTNColor,
|
|
26
25
|
ToEntryFn
|
|
27
26
|
} from '../../types';
|
|
28
27
|
import { IBinaryTree } from '../../interfaces';
|
|
@@ -34,59 +33,92 @@ import { DFSOperation, Range } from '../../common';
|
|
|
34
33
|
/**
|
|
35
34
|
* Represents a node in a binary tree.
|
|
36
35
|
* @template V - The type of data stored in the node.
|
|
37
|
-
* @template
|
|
36
|
+
* @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.
|
|
38
37
|
*/
|
|
39
|
-
export class BinaryTreeNode<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
parent?: NODE;
|
|
49
|
-
|
|
38
|
+
export class BinaryTreeNode<K = any, V = any> {
|
|
39
|
+
/**
|
|
40
|
+
* The constructor function initializes an object with a key and an optional value in TypeScript.
|
|
41
|
+
* @param {K} key - The `key` parameter in the constructor function is used to store the key value
|
|
42
|
+
* for the key-value pair.
|
|
43
|
+
* @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
|
|
44
|
+
* have to be provided when creating an instance of the class. If a `value` is not provided, it will
|
|
45
|
+
* default to `undefined`.
|
|
46
|
+
*/
|
|
50
47
|
constructor(key: K, value?: V) {
|
|
51
48
|
this.key = key;
|
|
52
49
|
this.value = value;
|
|
53
50
|
}
|
|
54
51
|
|
|
55
|
-
|
|
52
|
+
key: K;
|
|
53
|
+
|
|
54
|
+
value?: V;
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
parent?: BinaryTreeNode<K, V> = undefined;
|
|
57
|
+
|
|
58
|
+
_left?: OptNodeOrNull<BinaryTreeNode<K, V>> = undefined;
|
|
59
|
+
|
|
60
|
+
get left(): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
58
61
|
return this._left;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
set left(v: OptNodeOrNull<
|
|
64
|
+
set left(v: OptNodeOrNull<BinaryTreeNode<K, V>>) {
|
|
62
65
|
if (v) {
|
|
63
|
-
v.parent = this as unknown as
|
|
66
|
+
v.parent = this as unknown as BinaryTreeNode<K, V>;
|
|
64
67
|
}
|
|
65
68
|
this._left = v;
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
|
|
71
|
+
_right?: OptNodeOrNull<BinaryTreeNode<K, V>> = undefined;
|
|
69
72
|
|
|
70
|
-
get right(): OptNodeOrNull<
|
|
73
|
+
get right(): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
71
74
|
return this._right;
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
set right(v: OptNodeOrNull<
|
|
77
|
+
set right(v: OptNodeOrNull<BinaryTreeNode<K, V>>) {
|
|
75
78
|
if (v) {
|
|
76
|
-
v.parent = this
|
|
79
|
+
v.parent = this;
|
|
77
80
|
}
|
|
78
81
|
this._right = v;
|
|
79
82
|
}
|
|
80
83
|
|
|
84
|
+
_height: number = 0;
|
|
85
|
+
|
|
86
|
+
get height(): number {
|
|
87
|
+
return this._height;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
set height(value: number) {
|
|
91
|
+
this._height = value;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
_color: RBTNColor = 'BLACK';
|
|
95
|
+
|
|
96
|
+
get color(): RBTNColor {
|
|
97
|
+
return this._color;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
set color(value: RBTNColor) {
|
|
101
|
+
this._color = value;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
_count: number = 1;
|
|
105
|
+
|
|
106
|
+
get count(): number {
|
|
107
|
+
return this._count;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
set count(value: number) {
|
|
111
|
+
this._count = value;
|
|
112
|
+
}
|
|
113
|
+
|
|
81
114
|
get familyPosition(): FamilyPosition {
|
|
82
|
-
const that = this as unknown as NODE;
|
|
83
115
|
if (!this.parent) {
|
|
84
116
|
return this.left || this.right ? 'ROOT' : 'ISOLATED';
|
|
85
117
|
}
|
|
86
118
|
|
|
87
|
-
if (this.parent.left ===
|
|
119
|
+
if (this.parent.left === this) {
|
|
88
120
|
return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';
|
|
89
|
-
} else if (this.parent.right ===
|
|
121
|
+
} else if (this.parent.right === this) {
|
|
90
122
|
return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';
|
|
91
123
|
}
|
|
92
124
|
|
|
@@ -101,28 +133,23 @@ export class BinaryTreeNode<
|
|
|
101
133
|
* 4. Subtrees: Each child of a node forms the root of a subtree.
|
|
102
134
|
* 5. Leaf Nodes: Nodes without children are leaves.
|
|
103
135
|
*/
|
|
104
|
-
export class BinaryTree<
|
|
105
|
-
K = any,
|
|
106
|
-
V = any,
|
|
107
|
-
R = object,
|
|
108
|
-
NODE extends BinaryTreeNode<K, V, NODE> = BinaryTreeNode<K, V, BinaryTreeNodeNested<K, V>>,
|
|
109
|
-
TREE extends BinaryTree<K, V, R, NODE, TREE> = BinaryTree<K, V, R, NODE, BinaryTreeNested<K, V, R, NODE>>
|
|
110
|
-
>
|
|
136
|
+
export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>
|
|
111
137
|
extends IterableEntryBase<K, V | undefined>
|
|
112
|
-
implements IBinaryTree<K, V, R,
|
|
138
|
+
implements IBinaryTree<K, V, R, MK, MV, MR>
|
|
113
139
|
{
|
|
114
|
-
iterationType: IterationType = 'ITERATIVE';
|
|
115
|
-
|
|
116
140
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* @param [options] - The `options` parameter in the constructor is an object that can
|
|
123
|
-
* following properties:
|
|
141
|
+
* This TypeScript constructor function initializes a binary tree with optional options and adds
|
|
142
|
+
* elements based on the provided input.
|
|
143
|
+
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
|
|
144
|
+
* iterable that can contain either objects of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. It
|
|
145
|
+
* is used to initialize the binary tree with keys, nodes, entries, or raw data.
|
|
146
|
+
* @param [options] - The `options` parameter in the constructor is an optional object that can
|
|
147
|
+
* contain the following properties:
|
|
124
148
|
*/
|
|
125
|
-
constructor(
|
|
149
|
+
constructor(
|
|
150
|
+
keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R> = [],
|
|
151
|
+
options?: BinaryTreeOptions<K, V, R>
|
|
152
|
+
) {
|
|
126
153
|
super();
|
|
127
154
|
if (options) {
|
|
128
155
|
const { iterationType, toEntryFn, isMapMode } = options;
|
|
@@ -135,6 +162,8 @@ export class BinaryTree<
|
|
|
135
162
|
if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);
|
|
136
163
|
}
|
|
137
164
|
|
|
165
|
+
iterationType: IterationType = 'ITERATIVE';
|
|
166
|
+
|
|
138
167
|
protected _isMapMode = true;
|
|
139
168
|
|
|
140
169
|
get isMapMode() {
|
|
@@ -147,9 +176,9 @@ export class BinaryTree<
|
|
|
147
176
|
return this._store;
|
|
148
177
|
}
|
|
149
178
|
|
|
150
|
-
protected _root?: OptNodeOrNull<
|
|
179
|
+
protected _root?: OptNodeOrNull<BinaryTreeNode<K, V>>;
|
|
151
180
|
|
|
152
|
-
get root(): OptNodeOrNull<
|
|
181
|
+
get root(): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
153
182
|
return this._root;
|
|
154
183
|
}
|
|
155
184
|
|
|
@@ -159,9 +188,9 @@ export class BinaryTree<
|
|
|
159
188
|
return this._size;
|
|
160
189
|
}
|
|
161
190
|
|
|
162
|
-
protected _NIL:
|
|
191
|
+
protected _NIL: BinaryTreeNode<K, V> = new BinaryTreeNode<K, V>(NaN as K) as unknown as BinaryTreeNode<K, V>;
|
|
163
192
|
|
|
164
|
-
get NIL():
|
|
193
|
+
get NIL(): BinaryTreeNode<K, V> {
|
|
165
194
|
return this._NIL;
|
|
166
195
|
}
|
|
167
196
|
|
|
@@ -172,19 +201,25 @@ export class BinaryTree<
|
|
|
172
201
|
}
|
|
173
202
|
|
|
174
203
|
/**
|
|
204
|
+
* Time Complexity: O(1)
|
|
205
|
+
* Space Complexity: O(1)
|
|
206
|
+
*
|
|
175
207
|
* The function creates a new binary tree node with a specified key and optional value.
|
|
176
208
|
* @param {K} key - The `key` parameter is the key of the node being created in the binary tree.
|
|
177
209
|
* @param {V} [value] - The `value` parameter in the `createNode` function is optional, meaning it is
|
|
178
210
|
* not required to be provided when calling the function. If a `value` is provided, it should be of
|
|
179
211
|
* type `V`, which is the type of the value associated with the node.
|
|
180
212
|
* @returns A new BinaryTreeNode instance with the provided key and value is being returned, casted
|
|
181
|
-
* as
|
|
213
|
+
* as BinaryTreeNode<K, V>.
|
|
182
214
|
*/
|
|
183
|
-
createNode(key: K, value?: V):
|
|
184
|
-
return new BinaryTreeNode<K, V
|
|
215
|
+
createNode(key: K, value?: V): BinaryTreeNode<K, V> {
|
|
216
|
+
return new BinaryTreeNode<K, V>(key, this._isMapMode ? undefined : value);
|
|
185
217
|
}
|
|
186
218
|
|
|
187
219
|
/**
|
|
220
|
+
* Time Complexity: O(1)
|
|
221
|
+
* Space Complexity: O(1)
|
|
222
|
+
*
|
|
188
223
|
* The function creates a binary tree with the specified options.
|
|
189
224
|
* @param [options] - The `options` parameter in the `createTree` function is an optional parameter
|
|
190
225
|
* that allows you to provide partial configuration options for creating a binary tree. It is of type
|
|
@@ -192,56 +227,13 @@ export class BinaryTree<
|
|
|
192
227
|
* of properties
|
|
193
228
|
* @returns A new instance of a binary tree with the specified options is being returned.
|
|
194
229
|
*/
|
|
195
|
-
createTree(options?: BinaryTreeOptions<K, V, R>)
|
|
196
|
-
return new BinaryTree<K, V, R,
|
|
230
|
+
createTree(options?: BinaryTreeOptions<K, V, R>) {
|
|
231
|
+
return new BinaryTree<K, V, R, MK, MV, MR>([], {
|
|
197
232
|
iterationType: this.iterationType,
|
|
198
233
|
isMapMode: this._isMapMode,
|
|
199
234
|
toEntryFn: this._toEntryFn,
|
|
200
235
|
...options
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
|
|
206
|
-
* or returns null.
|
|
207
|
-
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
|
|
208
|
-
* `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeEntryOrRaw`, which
|
|
209
|
-
* can be of type `BTNRep<K, V, NODE>` or `R`. This parameter represents either a key, a
|
|
210
|
-
* node, an entry
|
|
211
|
-
* @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
|
|
212
|
-
* an optional parameter of type `V`. It represents the value associated with the key in the node
|
|
213
|
-
* being created. If a `value` is provided, it will be used when creating the node. If
|
|
214
|
-
* @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
|
|
215
|
-
* (`OptNodeOrNull<NODE>`) based on the input parameters provided. The function checks the type of the
|
|
216
|
-
* input parameter (`keyNodeEntryOrRaw`) and processes it accordingly to return a node or null
|
|
217
|
-
* value.
|
|
218
|
-
*/
|
|
219
|
-
keyValueNodeEntryRawToNodeAndValue(
|
|
220
|
-
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
|
|
221
|
-
value?: V
|
|
222
|
-
): [OptNodeOrNull<NODE>, V | undefined] {
|
|
223
|
-
if (keyNodeEntryOrRaw === undefined) return [undefined, undefined];
|
|
224
|
-
if (keyNodeEntryOrRaw === null) return [null, undefined];
|
|
225
|
-
|
|
226
|
-
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];
|
|
227
|
-
|
|
228
|
-
if (this.isEntry(keyNodeEntryOrRaw)) {
|
|
229
|
-
const [key, entryValue] = keyNodeEntryOrRaw;
|
|
230
|
-
if (key === undefined) return [undefined, undefined];
|
|
231
|
-
else if (key === null) return [null, undefined];
|
|
232
|
-
const finalValue = value ?? entryValue;
|
|
233
|
-
return [this.createNode(key, finalValue), finalValue];
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
237
|
-
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
|
|
238
|
-
const finalValue = value ?? entryValue;
|
|
239
|
-
if (this.isKey(key)) return [this.createNode(key, finalValue), finalValue];
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value), value];
|
|
243
|
-
|
|
244
|
-
return [undefined, undefined];
|
|
236
|
+
});
|
|
245
237
|
}
|
|
246
238
|
|
|
247
239
|
/**
|
|
@@ -250,8 +242,8 @@ export class BinaryTree<
|
|
|
250
242
|
*
|
|
251
243
|
* The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
|
|
252
244
|
* value and returns the corresponding node or null.
|
|
253
|
-
* @param {BTNRep<K, V,
|
|
254
|
-
* parameter in the `ensureNode` function can be of type `BTNRep<K, V,
|
|
245
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `keyNodeOrEntry`
|
|
246
|
+
* parameter in the `ensureNode` function can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. It
|
|
255
247
|
* is used to determine whether the input is a key, node, entry, or raw data. The
|
|
256
248
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
|
|
257
249
|
* is used to specify the type of iteration to be performed. It has a default value of
|
|
@@ -260,144 +252,174 @@ export class BinaryTree<
|
|
|
260
252
|
* conditions specified in the code snippet.
|
|
261
253
|
*/
|
|
262
254
|
ensureNode(
|
|
263
|
-
|
|
255
|
+
keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
264
256
|
iterationType: IterationType = this.iterationType
|
|
265
|
-
): OptNodeOrNull<
|
|
266
|
-
if (
|
|
267
|
-
if (
|
|
268
|
-
if (
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
257
|
+
): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
258
|
+
if (keyNodeOrEntry === null) return null;
|
|
259
|
+
if (keyNodeOrEntry === undefined) return;
|
|
260
|
+
if (keyNodeOrEntry === this._NIL) return;
|
|
261
|
+
|
|
262
|
+
if (this.isNode(keyNodeOrEntry)) return keyNodeOrEntry;
|
|
263
|
+
|
|
264
|
+
if (this.isEntry(keyNodeOrEntry)) {
|
|
265
|
+
const key = keyNodeOrEntry[0];
|
|
273
266
|
if (key === null) return null;
|
|
274
267
|
if (key === undefined) return;
|
|
275
268
|
return this.getNode(key, this._root, iterationType);
|
|
276
269
|
}
|
|
277
270
|
|
|
278
|
-
|
|
279
|
-
const [key] = this._toEntryFn(keyNodeEntryOrRaw as R);
|
|
280
|
-
if (this.isKey(key)) return this.getNode(key);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (this.isKey(keyNodeEntryOrRaw)) return this.getNode(keyNodeEntryOrRaw, this._root, iterationType);
|
|
284
|
-
return;
|
|
271
|
+
return this.getNode(keyNodeOrEntry, this._root, iterationType);
|
|
285
272
|
}
|
|
286
273
|
|
|
287
274
|
/**
|
|
275
|
+
* Time Complexity: O(1)
|
|
276
|
+
* Space Complexity: O(1)
|
|
277
|
+
*
|
|
288
278
|
* The function isNode checks if the input is an instance of BinaryTreeNode.
|
|
289
|
-
* @param {BTNRep<K, V,
|
|
290
|
-
* `
|
|
279
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The parameter
|
|
280
|
+
* `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is
|
|
291
281
|
* checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
|
|
292
282
|
* accordingly.
|
|
293
|
-
* @returns The function `isNode` is checking if the input `
|
|
283
|
+
* @returns The function `isNode` is checking if the input `keyNodeOrEntry` is an instance of
|
|
294
284
|
* `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If
|
|
295
285
|
* it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
|
|
296
286
|
* is not a node.
|
|
297
287
|
*/
|
|
298
|
-
isNode(
|
|
299
|
-
return
|
|
288
|
+
isNode(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> {
|
|
289
|
+
return keyNodeOrEntry instanceof BinaryTreeNode;
|
|
300
290
|
}
|
|
301
291
|
|
|
302
292
|
/**
|
|
293
|
+
* Time Complexity: O(1)
|
|
294
|
+
* Space Complexity: O(1)
|
|
295
|
+
*
|
|
303
296
|
* The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.
|
|
304
|
-
* @param {BTNRep<K, V,
|
|
297
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | R} keyNodeEntryOrRaw - BTNRep<K, V, BinaryTreeNode<K, V>>
|
|
305
298
|
* @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by
|
|
306
299
|
* checking if it is an object. If the parameter is an object, the function will return `true`,
|
|
307
300
|
* indicating that it is of type `R`.
|
|
308
301
|
*/
|
|
309
|
-
isRaw(keyNodeEntryOrRaw: BTNRep<K, V,
|
|
302
|
+
isRaw(keyNodeEntryOrRaw: BTNRep<K, V, BinaryTreeNode<K, V>> | R): keyNodeEntryOrRaw is R {
|
|
310
303
|
return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';
|
|
311
304
|
}
|
|
312
305
|
|
|
313
306
|
/**
|
|
307
|
+
* Time Complexity: O(1)
|
|
308
|
+
* Space Complexity: O(1)
|
|
309
|
+
*
|
|
314
310
|
* The function `isRealNode` checks if a given input is a valid node in a binary tree.
|
|
315
|
-
* @param {BTNRep<K, V,
|
|
316
|
-
* parameter in the `isRealNode` function can be of type `BTNRep<K, V,
|
|
317
|
-
* The function checks if the input parameter is a `
|
|
318
|
-
* @returns The function `isRealNode` is checking if the input `
|
|
311
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `keyNodeOrEntry`
|
|
312
|
+
* parameter in the `isRealNode` function can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`.
|
|
313
|
+
* The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal
|
|
314
|
+
* @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid
|
|
319
315
|
* node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
|
|
320
316
|
* values, it then calls the `isNode` method to further determine if the input is a node. The
|
|
321
317
|
* function will return a boolean value indicating whether the
|
|
322
318
|
*/
|
|
323
|
-
isRealNode(
|
|
324
|
-
if (
|
|
325
|
-
return this.isNode(
|
|
319
|
+
isRealNode(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> {
|
|
320
|
+
if (keyNodeOrEntry === this._NIL || keyNodeOrEntry === null || keyNodeOrEntry === undefined) return false;
|
|
321
|
+
return this.isNode(keyNodeOrEntry);
|
|
326
322
|
}
|
|
327
323
|
|
|
328
324
|
/**
|
|
325
|
+
* Time Complexity: O(1)
|
|
326
|
+
* Space Complexity: O(1)
|
|
327
|
+
*
|
|
329
328
|
* The function checks if a given input is a valid node or null.
|
|
330
|
-
* @param {BTNRep<K, V,
|
|
331
|
-
* `
|
|
332
|
-
* V,
|
|
329
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The parameter
|
|
330
|
+
* `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
|
|
331
|
+
* V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or
|
|
333
332
|
* @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
|
|
334
|
-
* `
|
|
333
|
+
* `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or
|
|
335
334
|
* `null`, and `false` otherwise.
|
|
336
335
|
*/
|
|
337
|
-
isRealNodeOrNull(
|
|
338
|
-
return
|
|
336
|
+
isRealNodeOrNull(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> | null {
|
|
337
|
+
return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);
|
|
339
338
|
}
|
|
340
339
|
|
|
341
340
|
/**
|
|
341
|
+
* Time Complexity: O(1)
|
|
342
|
+
* Space Complexity: O(1)
|
|
343
|
+
*
|
|
342
344
|
* The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
|
|
343
|
-
* @param {BTNRep<K, V,
|
|
344
|
-
*
|
|
345
|
-
* @returns The function is checking if the `
|
|
345
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - BTNRep<K, V,
|
|
346
|
+
* BinaryTreeNode<K, V>>
|
|
347
|
+
* @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`
|
|
346
348
|
* property of the current object and returning a boolean value based on that comparison.
|
|
347
349
|
*/
|
|
348
|
-
isNIL(
|
|
349
|
-
return
|
|
350
|
+
isNIL(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): boolean {
|
|
351
|
+
return keyNodeOrEntry === this._NIL;
|
|
350
352
|
}
|
|
351
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Time Complexity: O(1)
|
|
356
|
+
* Space Complexity: O(1)
|
|
357
|
+
*
|
|
358
|
+
* The function `isRange` checks if the input parameter is an instance of the `Range` class.
|
|
359
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>> | Range<K>}
|
|
360
|
+
* keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
|
|
361
|
+
* of type `BTNRep<K, V, BinaryTreeNode<K, V>>`, `NodePredicate<BinaryTreeNode<K, V>>`, or
|
|
362
|
+
* `Range<K>`. The function checks if the `keyNodeEntry
|
|
363
|
+
* @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an
|
|
364
|
+
* instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,
|
|
365
|
+
* indicating that the parameter is a `Range<K>`. If it is not an instance of `Range`, the function
|
|
366
|
+
* will return `false`.
|
|
367
|
+
*/
|
|
352
368
|
isRange(
|
|
353
|
-
|
|
354
|
-
):
|
|
355
|
-
return
|
|
369
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>> | Range<K>
|
|
370
|
+
): keyNodeEntryOrPredicate is Range<K> {
|
|
371
|
+
return keyNodeEntryOrPredicate instanceof Range;
|
|
356
372
|
}
|
|
357
373
|
|
|
358
374
|
/**
|
|
375
|
+
* Time Complexity: O(1)
|
|
376
|
+
* Space Complexity: O(1)
|
|
377
|
+
*
|
|
359
378
|
* The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
|
|
360
379
|
* tree.
|
|
361
|
-
* @param {BTNRep<K, V,
|
|
362
|
-
* `
|
|
380
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The parameter
|
|
381
|
+
* `keyNodeOrEntry` can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. It represents a
|
|
363
382
|
* key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
|
|
364
383
|
* provided
|
|
365
384
|
* @returns The function `isLeaf` returns a boolean value indicating whether the input
|
|
366
|
-
* `
|
|
385
|
+
* `keyNodeOrEntry` is a leaf node in a binary tree.
|
|
367
386
|
*/
|
|
368
|
-
isLeaf(
|
|
369
|
-
|
|
370
|
-
if (
|
|
371
|
-
if (
|
|
372
|
-
return !this.isRealNode(
|
|
387
|
+
isLeaf(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): boolean {
|
|
388
|
+
keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);
|
|
389
|
+
if (keyNodeOrEntry === undefined) return false;
|
|
390
|
+
if (keyNodeOrEntry === null) return true;
|
|
391
|
+
return !this.isRealNode(keyNodeOrEntry.left) && !this.isRealNode(keyNodeOrEntry.right);
|
|
373
392
|
}
|
|
374
393
|
|
|
375
394
|
/**
|
|
395
|
+
* Time Complexity: O(1)
|
|
396
|
+
* Space Complexity: O(1)
|
|
397
|
+
*
|
|
376
398
|
* The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
|
|
377
399
|
* with a length of 2.
|
|
378
|
-
* @param {BTNRep<K, V,
|
|
379
|
-
* parameter in the `isEntry` function can be of type `BTNRep<K, V,
|
|
380
|
-
* The function checks if the provided `
|
|
381
|
-
* @returns The `isEntry` function is checking if the `
|
|
400
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `keyNodeOrEntry`
|
|
401
|
+
* parameter in the `isEntry` function can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or type `R`.
|
|
402
|
+
* The function checks if the provided `keyNodeOrEntry` is of type `BTN
|
|
403
|
+
* @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array
|
|
382
404
|
* with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
|
|
383
405
|
* `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
|
|
384
406
|
*/
|
|
385
|
-
isEntry(
|
|
386
|
-
return Array.isArray(
|
|
407
|
+
isEntry(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BTNEntry<K, V> {
|
|
408
|
+
return Array.isArray(keyNodeOrEntry) && keyNodeOrEntry.length === 2;
|
|
387
409
|
}
|
|
388
410
|
|
|
389
411
|
/**
|
|
390
412
|
* Time Complexity O(1)
|
|
391
413
|
* Space Complexity O(1)
|
|
392
414
|
*
|
|
393
|
-
* The function `
|
|
415
|
+
* The function `isValidKey` checks if a given key is comparable.
|
|
394
416
|
* @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in
|
|
395
417
|
* TypeScript.
|
|
396
|
-
* @returns The function `
|
|
418
|
+
* @returns The function `isValidKey` is checking if the `key` parameter is `null` or if it is comparable.
|
|
397
419
|
* If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
|
|
398
420
|
* `isComparable` function, which is not provided in the code snippet.
|
|
399
421
|
*/
|
|
400
|
-
|
|
422
|
+
isValidKey(key: any): key is K {
|
|
401
423
|
if (key === null) return true;
|
|
402
424
|
return isComparable(key);
|
|
403
425
|
}
|
|
@@ -408,8 +430,8 @@ export class BinaryTree<
|
|
|
408
430
|
*
|
|
409
431
|
* The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
|
|
410
432
|
* and finding the correct insertion position.
|
|
411
|
-
* @param {BTNRep<K, V,
|
|
412
|
-
* seems to be for adding a new node to a binary tree structure. The `
|
|
433
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `add` method you provided
|
|
434
|
+
* seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`
|
|
413
435
|
* parameter in the method can accept different types of values:
|
|
414
436
|
* @param {V} [value] - The `value` parameter in the `add` method represents the value associated
|
|
415
437
|
* with the key that you want to add to the binary tree. When adding a key-value pair to the binary
|
|
@@ -419,8 +441,8 @@ export class BinaryTree<
|
|
|
419
441
|
* node was successful, and `false` if the insertion position could not be found or if a duplicate
|
|
420
442
|
* key was found and the node was replaced instead of inserted.
|
|
421
443
|
*/
|
|
422
|
-
add(
|
|
423
|
-
const [newNode, newValue] = this.
|
|
444
|
+
add(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>, value?: V): boolean {
|
|
445
|
+
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
424
446
|
if (newNode === undefined) return false;
|
|
425
447
|
|
|
426
448
|
// If the tree is empty, directly set the new node as the root node
|
|
@@ -431,8 +453,8 @@ export class BinaryTree<
|
|
|
431
453
|
return true;
|
|
432
454
|
}
|
|
433
455
|
|
|
434
|
-
const queue = new Queue<
|
|
435
|
-
let potentialParent:
|
|
456
|
+
const queue = new Queue<BinaryTreeNode<K, V>>([this._root]);
|
|
457
|
+
let potentialParent: BinaryTreeNode<K, V> | undefined; // Record the parent node of the potential insertion location
|
|
436
458
|
|
|
437
459
|
while (queue.size > 0) {
|
|
438
460
|
const cur = queue.shift();
|
|
@@ -477,14 +499,14 @@ export class BinaryTree<
|
|
|
477
499
|
|
|
478
500
|
/**
|
|
479
501
|
* Time Complexity: O(k * n)
|
|
480
|
-
* Space Complexity: O(
|
|
502
|
+
* Space Complexity: O(k)
|
|
481
503
|
*
|
|
482
504
|
* The `addMany` function takes in multiple keys or nodes or entries or raw values along with
|
|
483
505
|
* optional values, and adds them to a data structure while returning an array indicating whether
|
|
484
506
|
* each insertion was successful.
|
|
485
507
|
* @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
|
|
486
508
|
* mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
|
|
487
|
-
* `BTNRep<K, V,
|
|
509
|
+
* `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`.
|
|
488
510
|
* @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
|
|
489
511
|
* accepts an iterable of values. These values correspond to the keys or nodes being added in the
|
|
490
512
|
* `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
|
|
@@ -493,7 +515,10 @@ export class BinaryTree<
|
|
|
493
515
|
* node, entry, or raw value was successfully added to the data structure. Each boolean value
|
|
494
516
|
* corresponds to the success of adding the corresponding key or value in the input iterable.
|
|
495
517
|
*/
|
|
496
|
-
addMany(
|
|
518
|
+
addMany(
|
|
519
|
+
keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R>,
|
|
520
|
+
values?: Iterable<V | undefined>
|
|
521
|
+
): boolean[] {
|
|
497
522
|
// TODO not sure addMany not be run multi times
|
|
498
523
|
const inserted: boolean[] = [];
|
|
499
524
|
|
|
@@ -502,7 +527,7 @@ export class BinaryTree<
|
|
|
502
527
|
valuesIterator = values[Symbol.iterator]();
|
|
503
528
|
}
|
|
504
529
|
|
|
505
|
-
for (
|
|
530
|
+
for (let keyNodeEntryOrRaw of keysNodesEntriesOrRaws) {
|
|
506
531
|
let value: V | undefined | null = undefined;
|
|
507
532
|
|
|
508
533
|
if (valuesIterator) {
|
|
@@ -511,7 +536,7 @@ export class BinaryTree<
|
|
|
511
536
|
value = valueResult.value;
|
|
512
537
|
}
|
|
513
538
|
}
|
|
514
|
-
|
|
539
|
+
if (this.isRaw(keyNodeEntryOrRaw)) keyNodeEntryOrRaw = this._toEntryFn!(keyNodeEntryOrRaw);
|
|
515
540
|
inserted.push(this.add(keyNodeEntryOrRaw, value));
|
|
516
541
|
}
|
|
517
542
|
|
|
@@ -524,9 +549,9 @@ export class BinaryTree<
|
|
|
524
549
|
*
|
|
525
550
|
* The `merge` function in TypeScript merges another binary tree into the current tree by adding all
|
|
526
551
|
* elements from the other tree.
|
|
527
|
-
* @param anotherTree -
|
|
552
|
+
* @param anotherTree - BinaryTree<K, V, R, MK, MV, MR>
|
|
528
553
|
*/
|
|
529
|
-
merge(anotherTree: BinaryTree<K, V, R,
|
|
554
|
+
merge(anotherTree: BinaryTree<K, V, R, MK, MV, MR>) {
|
|
530
555
|
this.addMany(anotherTree, []);
|
|
531
556
|
}
|
|
532
557
|
|
|
@@ -537,12 +562,15 @@ export class BinaryTree<
|
|
|
537
562
|
* The `refill` function clears the existing data structure and then adds new key-value pairs based
|
|
538
563
|
* on the provided input.
|
|
539
564
|
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
|
|
540
|
-
* method can accept an iterable containing a mix of `BTNRep<K, V,
|
|
565
|
+
* method can accept an iterable containing a mix of `BTNRep<K, V, BinaryTreeNode<K, V>>` objects or `R`
|
|
541
566
|
* objects.
|
|
542
567
|
* @param [values] - The `values` parameter in the `refill` method is an optional parameter that
|
|
543
568
|
* accepts an iterable of values of type `V` or `undefined`.
|
|
544
569
|
*/
|
|
545
|
-
refill(
|
|
570
|
+
refill(
|
|
571
|
+
keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R>,
|
|
572
|
+
values?: Iterable<V | undefined>
|
|
573
|
+
): void {
|
|
546
574
|
this.clear();
|
|
547
575
|
this.addMany(keysNodesEntriesOrRaws, values);
|
|
548
576
|
}
|
|
@@ -553,7 +581,7 @@ export class BinaryTree<
|
|
|
553
581
|
*
|
|
554
582
|
* The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
|
|
555
583
|
* the deleted node along with information for tree balancing.
|
|
556
|
-
* @param {BTNRep<K, V,
|
|
584
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry
|
|
557
585
|
* - The `delete` method you provided is used to delete a node from a binary tree based on the key,
|
|
558
586
|
* node, entry or raw data. The method returns an array of
|
|
559
587
|
* `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
|
|
@@ -562,16 +590,16 @@ export class BinaryTree<
|
|
|
562
590
|
* the array contains information about the node that was deleted (`deleted`) and the node that may
|
|
563
591
|
* need to be balanced (`needBalanced`).
|
|
564
592
|
*/
|
|
565
|
-
delete(
|
|
566
|
-
const deletedResult: BinaryTreeDeleteResult<
|
|
593
|
+
delete(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
|
|
594
|
+
const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
|
|
567
595
|
if (!this._root) return deletedResult;
|
|
568
596
|
|
|
569
|
-
const curr = this.getNode(
|
|
597
|
+
const curr = this.getNode(keyNodeOrEntry);
|
|
570
598
|
if (!curr) return deletedResult;
|
|
571
599
|
|
|
572
|
-
const parent:
|
|
573
|
-
let needBalanced:
|
|
574
|
-
let orgCurrent:
|
|
600
|
+
const parent: BinaryTreeNode<K, V> | undefined = curr?.parent;
|
|
601
|
+
let needBalanced: BinaryTreeNode<K, V> | undefined;
|
|
602
|
+
let orgCurrent: BinaryTreeNode<K, V> | undefined = curr;
|
|
575
603
|
|
|
576
604
|
if (!curr.left && !curr.right && !parent) {
|
|
577
605
|
this._setRoot(undefined);
|
|
@@ -613,15 +641,15 @@ export class BinaryTree<
|
|
|
613
641
|
*
|
|
614
642
|
* The `search` function in TypeScript performs a depth-first or breadth-first search on a tree
|
|
615
643
|
* structure based on a given predicate or key, with options to return multiple results or just one.
|
|
616
|
-
* @param {BTNRep<K, V,
|
|
617
|
-
* `
|
|
644
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
|
|
645
|
+
* `keyNodeEntryOrPredicate` parameter in the `search` function can accept three types of values:
|
|
618
646
|
* @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that
|
|
619
647
|
* determines whether the search should stop after finding the first matching node. If `onlyOne` is
|
|
620
648
|
* set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is
|
|
621
649
|
* @param {C} callback - The `callback` parameter in the `search` function is a callback function
|
|
622
650
|
* that will be called on each node that matches the search criteria. It is of type `C`, which
|
|
623
|
-
* extends `NodeCallback<
|
|
624
|
-
* @param {BTNRep<K, V,
|
|
651
|
+
* extends `NodeCallback<BinaryTreeNode<K, V>>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if
|
|
652
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `search` function is
|
|
625
653
|
* used to specify the node from which the search operation should begin. It represents the starting
|
|
626
654
|
* point in the binary tree where the search will be performed. If no specific `startNode` is
|
|
627
655
|
* provided, the search operation will start from the root
|
|
@@ -631,23 +659,23 @@ export class BinaryTree<
|
|
|
631
659
|
* @returns The `search` function returns an array of values that match the provided criteria based
|
|
632
660
|
* on the search algorithm implemented within the function.
|
|
633
661
|
*/
|
|
634
|
-
search<C extends NodeCallback<
|
|
635
|
-
|
|
662
|
+
search<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
663
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
|
|
636
664
|
onlyOne = false,
|
|
637
665
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
638
|
-
startNode: BTNRep<K, V,
|
|
666
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
639
667
|
iterationType: IterationType = this.iterationType
|
|
640
668
|
): ReturnType<C>[] {
|
|
641
|
-
if (
|
|
642
|
-
if (
|
|
669
|
+
if (keyNodeEntryOrPredicate === undefined) return [];
|
|
670
|
+
if (keyNodeEntryOrPredicate === null) return [];
|
|
643
671
|
startNode = this.ensureNode(startNode);
|
|
644
672
|
if (!startNode) return [];
|
|
645
|
-
const predicate = this._ensurePredicate(
|
|
673
|
+
const predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
|
|
646
674
|
|
|
647
675
|
const ans: ReturnType<C>[] = [];
|
|
648
676
|
|
|
649
677
|
if (iterationType === 'RECURSIVE') {
|
|
650
|
-
const dfs = (cur:
|
|
678
|
+
const dfs = (cur: BinaryTreeNode<K, V>) => {
|
|
651
679
|
if (predicate(cur)) {
|
|
652
680
|
ans.push(callback(cur));
|
|
653
681
|
if (onlyOne) return;
|
|
@@ -682,12 +710,12 @@ export class BinaryTree<
|
|
|
682
710
|
*
|
|
683
711
|
* The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
|
|
684
712
|
* or predicate, with options for recursive or iterative traversal.
|
|
685
|
-
* @param {BTNRep<K, V,
|
|
713
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
686
714
|
* - The `getNodes` function you provided takes several parameters:
|
|
687
715
|
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
|
|
688
716
|
* determines whether to return only the first node that matches the criteria specified by the
|
|
689
|
-
* `
|
|
690
|
-
* @param {BTNRep<K, V,
|
|
717
|
+
* `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
|
|
718
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
691
719
|
* `getNodes` function is used to specify the starting point for traversing the binary tree. It
|
|
692
720
|
* represents the root node of the binary tree or the node from which the traversal should begin. If
|
|
693
721
|
* not provided, the default value is set to `this._root
|
|
@@ -698,24 +726,24 @@ export class BinaryTree<
|
|
|
698
726
|
* based on the input parameters and the iteration type specified.
|
|
699
727
|
*/
|
|
700
728
|
getNodes(
|
|
701
|
-
|
|
729
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
|
|
702
730
|
onlyOne = false,
|
|
703
|
-
startNode: BTNRep<K, V,
|
|
731
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
704
732
|
iterationType: IterationType = this.iterationType
|
|
705
|
-
):
|
|
706
|
-
return this.search(
|
|
733
|
+
): BinaryTreeNode<K, V>[] {
|
|
734
|
+
return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
|
|
707
735
|
}
|
|
708
736
|
|
|
709
737
|
/**
|
|
710
738
|
* Time Complexity: O(n)
|
|
711
|
-
* Space Complexity: O(log n)
|
|
739
|
+
* Space Complexity: O(log n)
|
|
712
740
|
*
|
|
713
741
|
* The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
|
|
714
742
|
* predicate.
|
|
715
|
-
* @param {BTNRep<K, V,
|
|
716
|
-
* - The `
|
|
743
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
744
|
+
* - The `keyNodeEntryOrPredicate` parameter in the `getNode` function can accept a key,
|
|
717
745
|
* node, entry, raw data, or a predicate function.
|
|
718
|
-
* @param {BTNRep<K, V,
|
|
746
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
719
747
|
* `getNode` function is used to specify the starting point for searching for a node in a binary
|
|
720
748
|
* tree. If no specific starting point is provided, the default value is set to `this._root`, which
|
|
721
749
|
* is typically the root node of the binary tree.
|
|
@@ -727,11 +755,11 @@ export class BinaryTree<
|
|
|
727
755
|
* or `null` if no matching node is found.
|
|
728
756
|
*/
|
|
729
757
|
getNode(
|
|
730
|
-
|
|
731
|
-
startNode: BTNRep<K, V,
|
|
758
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
|
|
759
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
732
760
|
iterationType: IterationType = this.iterationType
|
|
733
|
-
): OptNodeOrNull<
|
|
734
|
-
return this.search(
|
|
761
|
+
): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
762
|
+
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];
|
|
735
763
|
}
|
|
736
764
|
|
|
737
765
|
/**
|
|
@@ -740,10 +768,10 @@ export class BinaryTree<
|
|
|
740
768
|
*
|
|
741
769
|
* This function overrides the `get` method to retrieve the value associated with a specified key,
|
|
742
770
|
* node, entry, raw data, or predicate in a data structure.
|
|
743
|
-
* @param {BTNRep<K, V,
|
|
744
|
-
* - The `
|
|
771
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
772
|
+
* - The `keyNodeEntryOrPredicate` parameter in the `get` method can accept one of the
|
|
745
773
|
* following types:
|
|
746
|
-
* @param {BTNRep<K, V,
|
|
774
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `get`
|
|
747
775
|
* method is used to specify the starting point for searching for a key or node in the binary tree.
|
|
748
776
|
* If no specific starting point is provided, the default starting point is the root of the binary
|
|
749
777
|
* tree (`this._root`).
|
|
@@ -757,16 +785,16 @@ export class BinaryTree<
|
|
|
757
785
|
* `undefined`.
|
|
758
786
|
*/
|
|
759
787
|
override get(
|
|
760
|
-
|
|
761
|
-
startNode: BTNRep<K, V,
|
|
788
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
789
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
762
790
|
iterationType: IterationType = this.iterationType
|
|
763
791
|
): V | undefined {
|
|
764
792
|
if (this._isMapMode) {
|
|
765
|
-
const key = this._extractKey(
|
|
793
|
+
const key = this._extractKey(keyNodeEntryOrPredicate);
|
|
766
794
|
if (key === null || key === undefined) return;
|
|
767
795
|
return this._store.get(key);
|
|
768
796
|
}
|
|
769
|
-
return this.getNode(
|
|
797
|
+
return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;
|
|
770
798
|
}
|
|
771
799
|
|
|
772
800
|
/**
|
|
@@ -775,10 +803,10 @@ export class BinaryTree<
|
|
|
775
803
|
*
|
|
776
804
|
* The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
|
|
777
805
|
* exists in the data structure.
|
|
778
|
-
* @param {BTNRep<K, V,
|
|
779
|
-
* - The `
|
|
806
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
807
|
+
* - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of
|
|
780
808
|
* the following types:
|
|
781
|
-
* @param {BTNRep<K, V,
|
|
809
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
782
810
|
* `override` method is used to specify the starting point for the search operation within the data
|
|
783
811
|
* structure. It defaults to `this._root` if not provided explicitly.
|
|
784
812
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
|
|
@@ -791,18 +819,18 @@ export class BinaryTree<
|
|
|
791
819
|
* Otherwise, it returns `false`.
|
|
792
820
|
*/
|
|
793
821
|
override has(
|
|
794
|
-
|
|
795
|
-
startNode: BTNRep<K, V,
|
|
822
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
|
|
823
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
796
824
|
iterationType: IterationType = this.iterationType
|
|
797
825
|
): boolean {
|
|
798
|
-
return this.search(
|
|
826
|
+
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;
|
|
799
827
|
}
|
|
800
828
|
|
|
801
829
|
/**
|
|
802
830
|
* Time Complexity: O(1)
|
|
803
831
|
* Space Complexity: O(1)
|
|
804
832
|
*
|
|
805
|
-
* The
|
|
833
|
+
* The clear function removes nodes and values in map mode.
|
|
806
834
|
*/
|
|
807
835
|
clear() {
|
|
808
836
|
this._clearNodes();
|
|
@@ -828,7 +856,7 @@ export class BinaryTree<
|
|
|
828
856
|
*
|
|
829
857
|
* The function checks if a binary tree is perfectly balanced by comparing its minimum height with
|
|
830
858
|
* its height.
|
|
831
|
-
* @param {BTNRep<K, V,
|
|
859
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
832
860
|
* point for checking if the binary tree is perfectly balanced. It represents the root node of the
|
|
833
861
|
* binary tree or a specific node from which the balance check should begin.
|
|
834
862
|
* @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
|
|
@@ -837,17 +865,17 @@ export class BinaryTree<
|
|
|
837
865
|
* height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
|
|
838
866
|
* balanced and
|
|
839
867
|
*/
|
|
840
|
-
isPerfectlyBalanced(startNode: BTNRep<K, V,
|
|
868
|
+
isPerfectlyBalanced(startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root): boolean {
|
|
841
869
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
842
870
|
}
|
|
843
871
|
|
|
844
872
|
/**
|
|
845
873
|
* Time Complexity: O(n)
|
|
846
|
-
* Space Complexity: O(
|
|
874
|
+
* Space Complexity: O(log n)
|
|
847
875
|
*
|
|
848
876
|
* The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
|
|
849
877
|
* or iterative methods.
|
|
850
|
-
* @param {BTNRep<K, V,
|
|
878
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `isBST`
|
|
851
879
|
* function represents the starting point for checking whether a binary search tree (BST) is valid.
|
|
852
880
|
* It can be a node in the BST or a reference to the root of the BST. If no specific node is
|
|
853
881
|
* provided, the function will default to
|
|
@@ -859,13 +887,16 @@ export class BinaryTree<
|
|
|
859
887
|
* the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
|
|
860
888
|
* less than the node's key, and all nodes in its right subtree have keys greater than the node's
|
|
861
889
|
*/
|
|
862
|
-
isBST(
|
|
890
|
+
isBST(
|
|
891
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
892
|
+
iterationType: IterationType = this.iterationType
|
|
893
|
+
): boolean {
|
|
863
894
|
// TODO there is a bug
|
|
864
895
|
startNode = this.ensureNode(startNode);
|
|
865
896
|
if (!startNode) return true;
|
|
866
897
|
|
|
867
898
|
if (iterationType === 'RECURSIVE') {
|
|
868
|
-
const dfs = (cur: OptNodeOrNull<
|
|
899
|
+
const dfs = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>, min: number, max: number): boolean => {
|
|
869
900
|
if (!this.isRealNode(cur)) return true;
|
|
870
901
|
const numKey = Number(cur.key);
|
|
871
902
|
if (numKey <= min || numKey >= max) return false;
|
|
@@ -880,7 +911,7 @@ export class BinaryTree<
|
|
|
880
911
|
const stack = [];
|
|
881
912
|
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
882
913
|
// @ts-ignore
|
|
883
|
-
let curr: OptNodeOrNull<
|
|
914
|
+
let curr: OptNodeOrNull<BinaryTreeNode<K, V>> = startNode;
|
|
884
915
|
while (this.isRealNode(curr) || stack.length > 0) {
|
|
885
916
|
while (this.isRealNode(curr)) {
|
|
886
917
|
stack.push(curr);
|
|
@@ -902,13 +933,13 @@ export class BinaryTree<
|
|
|
902
933
|
|
|
903
934
|
/**
|
|
904
935
|
* Time Complexity: O(n)
|
|
905
|
-
* Space Complexity: O(
|
|
936
|
+
* Space Complexity: O(log n)
|
|
906
937
|
*
|
|
907
938
|
* The `getDepth` function calculates the depth between two nodes in a binary tree.
|
|
908
|
-
* @param {BTNRep<K, V,
|
|
939
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} dist - The `dist` parameter in the `getDepth`
|
|
909
940
|
* function represents the node or entry in a binary tree map, or a reference to a node in the tree.
|
|
910
941
|
* It is the target node for which you want to calculate the depth from the `startNode` node.
|
|
911
|
-
* @param {BTNRep<K, V,
|
|
942
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
912
943
|
* `getDepth` function represents the starting point from which you want to calculate the depth of a
|
|
913
944
|
* given node or entry in a binary tree. If no specific starting point is provided, the default value
|
|
914
945
|
* for `startNode` is set to the root of the binary
|
|
@@ -916,7 +947,10 @@ export class BinaryTree<
|
|
|
916
947
|
* `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
|
|
917
948
|
* node, it returns the depth of the `dist` node from the root of the tree.
|
|
918
949
|
*/
|
|
919
|
-
getDepth(
|
|
950
|
+
getDepth(
|
|
951
|
+
dist: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
952
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root
|
|
953
|
+
): number {
|
|
920
954
|
let distEnsured = this.ensureNode(dist);
|
|
921
955
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
922
956
|
let depth = 0;
|
|
@@ -932,11 +966,11 @@ export class BinaryTree<
|
|
|
932
966
|
|
|
933
967
|
/**
|
|
934
968
|
* Time Complexity: O(n)
|
|
935
|
-
* Space Complexity: O(
|
|
969
|
+
* Space Complexity: O(log n)
|
|
936
970
|
*
|
|
937
971
|
* The `getHeight` function calculates the maximum height of a binary tree using either a recursive
|
|
938
972
|
* or iterative approach in TypeScript.
|
|
939
|
-
* @param {BTNRep<K, V,
|
|
973
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
940
974
|
* point from which the height of the binary tree will be calculated. It can be a node in the binary
|
|
941
975
|
* tree or a reference to the root of the tree. If not provided, it defaults to the root of the
|
|
942
976
|
* binary tree data structure.
|
|
@@ -947,12 +981,15 @@ export class BinaryTree<
|
|
|
947
981
|
* root node. The height is calculated based on the maximum depth of the tree, considering either a
|
|
948
982
|
* recursive approach or an iterative approach depending on the `iterationType` parameter.
|
|
949
983
|
*/
|
|
950
|
-
getHeight(
|
|
984
|
+
getHeight(
|
|
985
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
986
|
+
iterationType: IterationType = this.iterationType
|
|
987
|
+
): number {
|
|
951
988
|
startNode = this.ensureNode(startNode);
|
|
952
989
|
if (!this.isRealNode(startNode)) return -1;
|
|
953
990
|
|
|
954
991
|
if (iterationType === 'RECURSIVE') {
|
|
955
|
-
const _getMaxHeight = (cur: OptNodeOrNull<
|
|
992
|
+
const _getMaxHeight = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>): number => {
|
|
956
993
|
if (!this.isRealNode(cur)) return -1;
|
|
957
994
|
const leftHeight = _getMaxHeight(cur.left);
|
|
958
995
|
const rightHeight = _getMaxHeight(cur.right);
|
|
@@ -961,7 +998,7 @@ export class BinaryTree<
|
|
|
961
998
|
|
|
962
999
|
return _getMaxHeight(startNode);
|
|
963
1000
|
} else {
|
|
964
|
-
const stack: { node:
|
|
1001
|
+
const stack: { node: BinaryTreeNode<K, V>; depth: number }[] = [{ node: startNode, depth: 0 }];
|
|
965
1002
|
let maxHeight = 0;
|
|
966
1003
|
|
|
967
1004
|
while (stack.length > 0) {
|
|
@@ -983,7 +1020,7 @@ export class BinaryTree<
|
|
|
983
1020
|
*
|
|
984
1021
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
985
1022
|
* recursive or iterative approach in TypeScript.
|
|
986
|
-
* @param {BTNRep<K, V,
|
|
1023
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
987
1024
|
* `getMinHeight` function represents the starting node from which the minimum height of the binary
|
|
988
1025
|
* tree will be calculated. It is either a node in the binary tree or a reference to the root of the
|
|
989
1026
|
* tree. If not provided, the default value is the root
|
|
@@ -996,14 +1033,14 @@ export class BinaryTree<
|
|
|
996
1033
|
* a stack) based on the `iterationType` parameter.
|
|
997
1034
|
*/
|
|
998
1035
|
getMinHeight(
|
|
999
|
-
startNode: BTNRep<K, V,
|
|
1036
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1000
1037
|
iterationType: IterationType = this.iterationType
|
|
1001
1038
|
): number {
|
|
1002
1039
|
startNode = this.ensureNode(startNode);
|
|
1003
1040
|
if (!startNode) return -1;
|
|
1004
1041
|
|
|
1005
1042
|
if (iterationType === 'RECURSIVE') {
|
|
1006
|
-
const _getMinHeight = (cur: OptNodeOrNull<
|
|
1043
|
+
const _getMinHeight = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>): number => {
|
|
1007
1044
|
if (!this.isRealNode(cur)) return 0;
|
|
1008
1045
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
|
|
1009
1046
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
@@ -1013,10 +1050,10 @@ export class BinaryTree<
|
|
|
1013
1050
|
|
|
1014
1051
|
return _getMinHeight(startNode);
|
|
1015
1052
|
} else {
|
|
1016
|
-
const stack:
|
|
1017
|
-
let node: OptNodeOrNull<
|
|
1018
|
-
last: OptNodeOrNull<
|
|
1019
|
-
const depths: Map<
|
|
1053
|
+
const stack: BinaryTreeNode<K, V>[] = [];
|
|
1054
|
+
let node: OptNodeOrNull<BinaryTreeNode<K, V>> = startNode,
|
|
1055
|
+
last: OptNodeOrNull<BinaryTreeNode<K, V>> = null;
|
|
1056
|
+
const depths: Map<BinaryTreeNode<K, V>, number> = new Map();
|
|
1020
1057
|
|
|
1021
1058
|
while (stack.length > 0 || node) {
|
|
1022
1059
|
if (this.isRealNode(node)) {
|
|
@@ -1051,7 +1088,7 @@ export class BinaryTree<
|
|
|
1051
1088
|
* the path to the root. It is expected to be a function that takes a node as an argument and returns
|
|
1052
1089
|
* a value based on that node. The return type of the callback function is determined by the generic
|
|
1053
1090
|
* type `C
|
|
1054
|
-
* @param {BTNRep<K, V,
|
|
1091
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} beginNode - The `beginNode` parameter in the
|
|
1055
1092
|
* `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
|
|
1056
1093
|
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
|
|
1057
1094
|
* whether the resulting path from the given `beginNode` to the root should be in reverse order or
|
|
@@ -1061,8 +1098,8 @@ export class BinaryTree<
|
|
|
1061
1098
|
* array is either in reverse order or in the original order based on the value of the `isReverse`
|
|
1062
1099
|
* parameter.
|
|
1063
1100
|
*/
|
|
1064
|
-
getPathToRoot<C extends NodeCallback<OptNodeOrNull<
|
|
1065
|
-
beginNode: BTNRep<K, V,
|
|
1101
|
+
getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1102
|
+
beginNode: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1066
1103
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1067
1104
|
isReverse = false
|
|
1068
1105
|
): ReturnType<C>[] {
|
|
@@ -1082,14 +1119,14 @@ export class BinaryTree<
|
|
|
1082
1119
|
|
|
1083
1120
|
/**
|
|
1084
1121
|
* Time Complexity: O(log n)
|
|
1085
|
-
* Space Complexity: O(
|
|
1122
|
+
* Space Complexity: O(log n)
|
|
1086
1123
|
*
|
|
1087
1124
|
* The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or
|
|
1088
1125
|
* tail-recursive iteration.
|
|
1089
1126
|
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
1090
1127
|
* node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
|
|
1091
1128
|
* value of `_DEFAULT_NODE_CALLBACK` if not specified.
|
|
1092
|
-
* @param {BTNRep<K, V,
|
|
1129
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1093
1130
|
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
1094
1131
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1095
1132
|
* starting point is provided, the function will default
|
|
@@ -1101,9 +1138,9 @@ export class BinaryTree<
|
|
|
1101
1138
|
* `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`
|
|
1102
1139
|
* node is not a real node, it returns the result of the callback
|
|
1103
1140
|
*/
|
|
1104
|
-
getLeftMost<C extends NodeCallback<OptNodeOrNull<
|
|
1141
|
+
getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1105
1142
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1106
|
-
startNode: BTNRep<K, V,
|
|
1143
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1107
1144
|
iterationType: IterationType = this.iterationType
|
|
1108
1145
|
): ReturnType<C> {
|
|
1109
1146
|
if (this.isNIL(startNode)) return callback(undefined);
|
|
@@ -1112,7 +1149,7 @@ export class BinaryTree<
|
|
|
1112
1149
|
if (!this.isRealNode(startNode)) return callback(startNode);
|
|
1113
1150
|
|
|
1114
1151
|
if (iterationType === 'RECURSIVE') {
|
|
1115
|
-
const dfs = (cur:
|
|
1152
|
+
const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
|
|
1116
1153
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1117
1154
|
return dfs(cur.left);
|
|
1118
1155
|
};
|
|
@@ -1120,7 +1157,7 @@ export class BinaryTree<
|
|
|
1120
1157
|
return callback(dfs(startNode));
|
|
1121
1158
|
} else {
|
|
1122
1159
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1123
|
-
const dfs = trampoline((cur:
|
|
1160
|
+
const dfs = trampoline((cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
|
|
1124
1161
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1125
1162
|
return dfs.cont(cur.left);
|
|
1126
1163
|
});
|
|
@@ -1131,15 +1168,15 @@ export class BinaryTree<
|
|
|
1131
1168
|
|
|
1132
1169
|
/**
|
|
1133
1170
|
* Time Complexity: O(log n)
|
|
1134
|
-
* Space Complexity: O(
|
|
1171
|
+
* Space Complexity: O(log n)
|
|
1135
1172
|
*
|
|
1136
1173
|
* The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
|
|
1137
1174
|
* or iterative traversal methods.
|
|
1138
1175
|
* @param {C} callback - The `callback` parameter is a function that will be called with the result
|
|
1139
|
-
* of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<
|
|
1176
|
+
* of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`,
|
|
1140
1177
|
* which means it is a callback function that can accept either an optional binary tree node or null
|
|
1141
1178
|
* as
|
|
1142
|
-
* @param {BTNRep<K, V,
|
|
1179
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1143
1180
|
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
1144
1181
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1145
1182
|
* starting point is provided, the function will default
|
|
@@ -1151,9 +1188,9 @@ export class BinaryTree<
|
|
|
1151
1188
|
* the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
|
|
1152
1189
|
* other).
|
|
1153
1190
|
*/
|
|
1154
|
-
getRightMost<C extends NodeCallback<OptNodeOrNull<
|
|
1191
|
+
getRightMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1155
1192
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1156
|
-
startNode: BTNRep<K, V,
|
|
1193
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1157
1194
|
iterationType: IterationType = this.iterationType
|
|
1158
1195
|
): ReturnType<C> {
|
|
1159
1196
|
if (this.isNIL(startNode)) return callback(undefined);
|
|
@@ -1161,7 +1198,7 @@ export class BinaryTree<
|
|
|
1161
1198
|
if (!startNode) return callback(startNode);
|
|
1162
1199
|
|
|
1163
1200
|
if (iterationType === 'RECURSIVE') {
|
|
1164
|
-
const dfs = (cur:
|
|
1201
|
+
const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
|
|
1165
1202
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1166
1203
|
return dfs(cur.right);
|
|
1167
1204
|
};
|
|
@@ -1169,7 +1206,7 @@ export class BinaryTree<
|
|
|
1169
1206
|
return callback(dfs(startNode));
|
|
1170
1207
|
} else {
|
|
1171
1208
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1172
|
-
const dfs = trampoline((cur:
|
|
1209
|
+
const dfs = trampoline((cur: BinaryTreeNode<K, V>) => {
|
|
1173
1210
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1174
1211
|
return dfs.cont(cur.right);
|
|
1175
1212
|
});
|
|
@@ -1180,20 +1217,20 @@ export class BinaryTree<
|
|
|
1180
1217
|
|
|
1181
1218
|
/**
|
|
1182
1219
|
* Time Complexity: O(log n)
|
|
1183
|
-
* Space Complexity: O(
|
|
1220
|
+
* Space Complexity: O(log n)
|
|
1184
1221
|
*
|
|
1185
1222
|
* The function `getPredecessor` in TypeScript returns the predecessor node of a given node in a
|
|
1186
1223
|
* binary tree.
|
|
1187
|
-
* @param {
|
|
1224
|
+
* @param {BinaryTreeNode<K, V>} node - The `getPredecessor` function you provided seems to be attempting to find the
|
|
1188
1225
|
* predecessor of a given node in a binary tree. However, there seems to be a logical issue in the
|
|
1189
1226
|
* while loop condition that might cause an infinite loop.
|
|
1190
|
-
* @returns The `getPredecessor` function returns the predecessor node of the input `
|
|
1227
|
+
* @returns The `getPredecessor` function returns the predecessor node of the input `BinaryTreeNode<K, V>` parameter.
|
|
1191
1228
|
* If the left child of the input node exists, it traverses to the rightmost node of the left subtree
|
|
1192
1229
|
* to find the predecessor. If the left child does not exist, it returns the input node itself.
|
|
1193
1230
|
*/
|
|
1194
|
-
getPredecessor(node:
|
|
1231
|
+
getPredecessor(node: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
|
|
1195
1232
|
if (this.isRealNode(node.left)) {
|
|
1196
|
-
let predecessor: OptNodeOrNull<
|
|
1233
|
+
let predecessor: OptNodeOrNull<BinaryTreeNode<K, V>> = node.left;
|
|
1197
1234
|
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1198
1235
|
if (this.isRealNode(predecessor)) {
|
|
1199
1236
|
predecessor = predecessor.right;
|
|
@@ -1207,18 +1244,18 @@ export class BinaryTree<
|
|
|
1207
1244
|
|
|
1208
1245
|
/**
|
|
1209
1246
|
* Time Complexity: O(log n)
|
|
1210
|
-
* Space Complexity: O(
|
|
1247
|
+
* Space Complexity: O(log n)
|
|
1211
1248
|
*
|
|
1212
1249
|
* The function `getSuccessor` in TypeScript returns the next node in an in-order traversal of a
|
|
1213
1250
|
* binary tree.
|
|
1214
|
-
* @param {K |
|
|
1215
|
-
* type `K`, `
|
|
1251
|
+
* @param {K | BinaryTreeNode<K, V> | null} [x] - The `getSuccessor` function takes a parameter `x`, which can be of
|
|
1252
|
+
* type `K`, `BinaryTreeNode<K, V>`, or `null`.
|
|
1216
1253
|
* @returns The `getSuccessor` function returns the successor node of the input node `x`. If `x` has
|
|
1217
1254
|
* a right child, the function returns the leftmost node in the right subtree of `x`. If `x` does not
|
|
1218
1255
|
* have a right child, the function traverses up the parent nodes until it finds a node that is not
|
|
1219
1256
|
* the right child of its parent, and returns that node
|
|
1220
1257
|
*/
|
|
1221
|
-
getSuccessor(x?: K |
|
|
1258
|
+
getSuccessor(x?: K | BinaryTreeNode<K, V> | null): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
1222
1259
|
x = this.ensureNode(x);
|
|
1223
1260
|
if (!this.isRealNode(x)) return undefined;
|
|
1224
1261
|
|
|
@@ -1226,7 +1263,7 @@ export class BinaryTree<
|
|
|
1226
1263
|
return this.getLeftMost(node => node, x.right);
|
|
1227
1264
|
}
|
|
1228
1265
|
|
|
1229
|
-
let y: OptNodeOrNull<
|
|
1266
|
+
let y: OptNodeOrNull<BinaryTreeNode<K, V>> = x.parent;
|
|
1230
1267
|
while (this.isRealNode(y) && x === y.right) {
|
|
1231
1268
|
x = y;
|
|
1232
1269
|
y = y.parent;
|
|
@@ -1234,17 +1271,17 @@ export class BinaryTree<
|
|
|
1234
1271
|
return y;
|
|
1235
1272
|
}
|
|
1236
1273
|
|
|
1237
|
-
dfs<C extends NodeCallback<
|
|
1274
|
+
dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1238
1275
|
callback?: C,
|
|
1239
1276
|
pattern?: DFSOrderPattern,
|
|
1240
|
-
startNode?: BTNRep<K, V,
|
|
1277
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1241
1278
|
iterationType?: IterationType
|
|
1242
1279
|
): ReturnType<C>[];
|
|
1243
1280
|
|
|
1244
|
-
dfs<C extends NodeCallback<
|
|
1281
|
+
dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1245
1282
|
callback?: C,
|
|
1246
1283
|
pattern?: DFSOrderPattern,
|
|
1247
|
-
startNode?: BTNRep<K, V,
|
|
1284
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1248
1285
|
iterationType?: IterationType,
|
|
1249
1286
|
includeNull?: boolean
|
|
1250
1287
|
): ReturnType<C>[];
|
|
@@ -1256,12 +1293,12 @@ export class BinaryTree<
|
|
|
1256
1293
|
* The function `dfs` performs a depth-first search traversal on a binary tree structure based on the
|
|
1257
1294
|
* specified parameters.
|
|
1258
1295
|
* @param {C} callback - The `callback` parameter is a generic type `C` that extends the
|
|
1259
|
-
* `NodeCallback` interface with a type parameter of `OptNodeOrNull<
|
|
1296
|
+
* `NodeCallback` interface with a type parameter of `OptNodeOrNull<BinaryTreeNode<K, V>>`. It has a default value of
|
|
1260
1297
|
* `this._DEFAULT_NODE_CALLBACK as C`.
|
|
1261
1298
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` method specifies the
|
|
1262
1299
|
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in the tree. The
|
|
1263
1300
|
* possible values for the `pattern` parameter are:
|
|
1264
|
-
* @param {BTNRep<K, V,
|
|
1301
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `dfs`
|
|
1265
1302
|
* method is used to specify the starting point for the Depth-First Search traversal. It can be
|
|
1266
1303
|
* either a `BTNRep` object representing a key, node, or entry in the binary tree map,
|
|
1267
1304
|
* or it can be a
|
|
@@ -1275,10 +1312,10 @@ export class BinaryTree<
|
|
|
1275
1312
|
* @returns The `dfs` method is returning an array of the return type specified by the generic type
|
|
1276
1313
|
* parameter `C`. The return type is determined by the callback function provided to the method.
|
|
1277
1314
|
*/
|
|
1278
|
-
dfs<C extends NodeCallback<OptNodeOrNull<
|
|
1315
|
+
dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1279
1316
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1280
1317
|
pattern: DFSOrderPattern = 'IN',
|
|
1281
|
-
startNode: BTNRep<K, V,
|
|
1318
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1282
1319
|
iterationType: IterationType = this.iterationType,
|
|
1283
1320
|
includeNull = false
|
|
1284
1321
|
): ReturnType<C>[] {
|
|
@@ -1287,16 +1324,16 @@ export class BinaryTree<
|
|
|
1287
1324
|
return this._dfs(callback, pattern, startNode, iterationType, includeNull);
|
|
1288
1325
|
}
|
|
1289
1326
|
|
|
1290
|
-
bfs<C extends NodeCallback<
|
|
1327
|
+
bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1291
1328
|
callback?: C,
|
|
1292
|
-
startNode?: BTNRep<K, V,
|
|
1329
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1293
1330
|
iterationType?: IterationType,
|
|
1294
1331
|
includeNull?: false
|
|
1295
1332
|
): ReturnType<C>[];
|
|
1296
1333
|
|
|
1297
|
-
bfs<C extends NodeCallback<
|
|
1334
|
+
bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1298
1335
|
callback?: C,
|
|
1299
|
-
startNode?: BTNRep<K, V,
|
|
1336
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1300
1337
|
iterationType?: IterationType,
|
|
1301
1338
|
includeNull?: true
|
|
1302
1339
|
): ReturnType<C>[];
|
|
@@ -1309,8 +1346,8 @@ export class BinaryTree<
|
|
|
1309
1346
|
* tree, executing a specified callback function on each node visited.
|
|
1310
1347
|
* @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
|
|
1311
1348
|
* called on each node visited during the breadth-first search traversal. It is a generic type `C`
|
|
1312
|
-
* that extends the `NodeCallback` type, which takes a parameter of type `
|
|
1313
|
-
* @param {BTNRep<K, V,
|
|
1349
|
+
* that extends the `NodeCallback` type, which takes a parameter of type `BinaryTreeNode<K, V>` or `null`.
|
|
1350
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `bfs`
|
|
1314
1351
|
* function represents the starting point for the breadth-first search traversal in a binary tree. It
|
|
1315
1352
|
* can be specified as a key, node, or entry in the binary tree structure. If not provided, the
|
|
1316
1353
|
* default value is the root node of the binary
|
|
@@ -1324,19 +1361,21 @@ export class BinaryTree<
|
|
|
1324
1361
|
* @returns The `bfs` function returns an array of values that are the result of applying the
|
|
1325
1362
|
* provided callback function to each node in the binary tree in a breadth-first search manner.
|
|
1326
1363
|
*/
|
|
1327
|
-
bfs<C extends NodeCallback<
|
|
1364
|
+
bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1328
1365
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1329
|
-
startNode: BTNRep<K, V,
|
|
1366
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1330
1367
|
iterationType: IterationType = this.iterationType,
|
|
1331
1368
|
includeNull = false
|
|
1332
1369
|
): ReturnType<C>[] {
|
|
1333
1370
|
startNode = this.ensureNode(startNode);
|
|
1334
1371
|
if (!startNode) return [];
|
|
1335
1372
|
|
|
1336
|
-
const ans: ReturnType<NodeCallback<
|
|
1373
|
+
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
|
|
1337
1374
|
|
|
1338
1375
|
if (iterationType === 'RECURSIVE') {
|
|
1339
|
-
const queue: Queue<OptNodeOrNull<
|
|
1376
|
+
const queue: Queue<OptNodeOrNull<BinaryTreeNode<K, V>>> = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([
|
|
1377
|
+
startNode
|
|
1378
|
+
]);
|
|
1340
1379
|
|
|
1341
1380
|
const dfs = (level: number) => {
|
|
1342
1381
|
if (queue.size === 0) return;
|
|
@@ -1357,7 +1396,7 @@ export class BinaryTree<
|
|
|
1357
1396
|
|
|
1358
1397
|
dfs(0);
|
|
1359
1398
|
} else {
|
|
1360
|
-
const queue = new Queue<OptNodeOrNull<
|
|
1399
|
+
const queue = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([startNode]);
|
|
1361
1400
|
while (queue.size > 0) {
|
|
1362
1401
|
const levelSize = queue.size;
|
|
1363
1402
|
|
|
@@ -1386,7 +1425,7 @@ export class BinaryTree<
|
|
|
1386
1425
|
* structure based on a specified callback and iteration type.
|
|
1387
1426
|
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1388
1427
|
* in the binary tree. It is optional and defaults to a default callback function if not provided.
|
|
1389
|
-
* @param {BTNRep<K, V,
|
|
1428
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `leaves`
|
|
1390
1429
|
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1391
1430
|
* tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
|
|
1392
1431
|
* explicitly provided, the default value
|
|
@@ -1396,17 +1435,17 @@ export class BinaryTree<
|
|
|
1396
1435
|
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1397
1436
|
* provided callback function to each leaf node in the binary tree.
|
|
1398
1437
|
*/
|
|
1399
|
-
leaves<C extends NodeCallback<
|
|
1438
|
+
leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1400
1439
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1401
|
-
startNode: BTNRep<K, V,
|
|
1440
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1402
1441
|
iterationType: IterationType = this.iterationType
|
|
1403
1442
|
): ReturnType<C>[] {
|
|
1404
1443
|
startNode = this.ensureNode(startNode);
|
|
1405
|
-
const leaves: ReturnType<NodeCallback<
|
|
1444
|
+
const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
|
|
1406
1445
|
if (!this.isRealNode(startNode)) return [];
|
|
1407
1446
|
|
|
1408
1447
|
if (iterationType === 'RECURSIVE') {
|
|
1409
|
-
const dfs = (cur:
|
|
1448
|
+
const dfs = (cur: BinaryTreeNode<K, V>) => {
|
|
1410
1449
|
if (this.isLeaf(cur)) {
|
|
1411
1450
|
leaves.push(callback(cur));
|
|
1412
1451
|
}
|
|
@@ -1433,16 +1472,16 @@ export class BinaryTree<
|
|
|
1433
1472
|
return leaves;
|
|
1434
1473
|
}
|
|
1435
1474
|
|
|
1436
|
-
listLevels<C extends NodeCallback<
|
|
1475
|
+
listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1437
1476
|
callback?: C,
|
|
1438
|
-
startNode?: BTNRep<K, V,
|
|
1477
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1439
1478
|
iterationType?: IterationType,
|
|
1440
1479
|
includeNull?: false
|
|
1441
1480
|
): ReturnType<C>[][];
|
|
1442
1481
|
|
|
1443
|
-
listLevels<C extends NodeCallback<
|
|
1482
|
+
listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1444
1483
|
callback?: C,
|
|
1445
|
-
startNode?: BTNRep<K, V,
|
|
1484
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1446
1485
|
iterationType?: IterationType,
|
|
1447
1486
|
includeNull?: true
|
|
1448
1487
|
): ReturnType<C>[][];
|
|
@@ -1456,7 +1495,7 @@ export class BinaryTree<
|
|
|
1456
1495
|
* @param {C} callback - The `callback` parameter is a function that will be applied to each node in
|
|
1457
1496
|
* the binary tree during the traversal. It is used to process each node and determine what
|
|
1458
1497
|
* information to include in the output for each level of the tree.
|
|
1459
|
-
* @param {BTNRep<K, V,
|
|
1498
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1460
1499
|
* `listLevels` function represents the starting point for traversing the binary tree. It can be
|
|
1461
1500
|
* either a key, a node, or an entry in the binary tree. If not provided, the default value is the
|
|
1462
1501
|
* root of the binary tree.
|
|
@@ -1471,9 +1510,9 @@ export class BinaryTree<
|
|
|
1471
1510
|
* level in a binary tree. Each inner array contains the return value of the provided callback
|
|
1472
1511
|
* function applied to the nodes at that level.
|
|
1473
1512
|
*/
|
|
1474
|
-
listLevels<C extends NodeCallback<
|
|
1513
|
+
listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1475
1514
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1476
|
-
startNode: BTNRep<K, V,
|
|
1515
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1477
1516
|
iterationType: IterationType = this.iterationType,
|
|
1478
1517
|
includeNull = false
|
|
1479
1518
|
): ReturnType<C>[][] {
|
|
@@ -1482,7 +1521,7 @@ export class BinaryTree<
|
|
|
1482
1521
|
if (!startNode) return levelsNodes;
|
|
1483
1522
|
|
|
1484
1523
|
if (iterationType === 'RECURSIVE') {
|
|
1485
|
-
const _recursive = (node:
|
|
1524
|
+
const _recursive = (node: BinaryTreeNode<K, V> | null, level: number) => {
|
|
1486
1525
|
if (!levelsNodes[level]) levelsNodes[level] = [];
|
|
1487
1526
|
levelsNodes[level].push(callback(node));
|
|
1488
1527
|
if (includeNull) {
|
|
@@ -1496,7 +1535,7 @@ export class BinaryTree<
|
|
|
1496
1535
|
|
|
1497
1536
|
_recursive(startNode, 0);
|
|
1498
1537
|
} else {
|
|
1499
|
-
const stack: [
|
|
1538
|
+
const stack: [BinaryTreeNode<K, V> | null, number][] = [[startNode, 0]];
|
|
1500
1539
|
|
|
1501
1540
|
while (stack.length > 0) {
|
|
1502
1541
|
const head = stack.pop()!;
|
|
@@ -1526,11 +1565,11 @@ export class BinaryTree<
|
|
|
1526
1565
|
* Morris Traversal algorithm with different order patterns.
|
|
1527
1566
|
* @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
|
|
1528
1567
|
* called on each node in the binary tree during the traversal. It is of type `C`, which extends the
|
|
1529
|
-
* `NodeCallback<
|
|
1568
|
+
* `NodeCallback<BinaryTreeNode<K, V>>` type. The default value for `callback` is `this._DEFAULT
|
|
1530
1569
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
|
|
1531
1570
|
* the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
|
|
1532
1571
|
* values for the `pattern` parameter are:
|
|
1533
|
-
* @param {BTNRep<K, V,
|
|
1572
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `morris`
|
|
1534
1573
|
* function is the starting point for the Morris traversal algorithm. It represents the root node of
|
|
1535
1574
|
* the binary tree or the node from which the traversal should begin. It can be provided as either a
|
|
1536
1575
|
* key, a node, an entry, or a reference
|
|
@@ -1538,19 +1577,19 @@ export class BinaryTree<
|
|
|
1538
1577
|
* provided callback function to each node in the binary tree in the specified order pattern (IN,
|
|
1539
1578
|
* PRE, or POST).
|
|
1540
1579
|
*/
|
|
1541
|
-
morris<C extends NodeCallback<
|
|
1580
|
+
morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1542
1581
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1543
1582
|
pattern: DFSOrderPattern = 'IN',
|
|
1544
|
-
startNode: BTNRep<K, V,
|
|
1583
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root
|
|
1545
1584
|
): ReturnType<C>[] {
|
|
1546
1585
|
startNode = this.ensureNode(startNode);
|
|
1547
1586
|
if (!startNode) return [];
|
|
1548
|
-
const ans: ReturnType<NodeCallback<
|
|
1587
|
+
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
|
|
1549
1588
|
|
|
1550
|
-
let cur: OptNodeOrNull<
|
|
1551
|
-
const _reverseEdge = (node: OptNodeOrNull<
|
|
1552
|
-
let pre: OptNodeOrNull<
|
|
1553
|
-
let next: OptNodeOrNull<
|
|
1589
|
+
let cur: OptNodeOrNull<BinaryTreeNode<K, V>> = startNode;
|
|
1590
|
+
const _reverseEdge = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => {
|
|
1591
|
+
let pre: OptNodeOrNull<BinaryTreeNode<K, V>> = null;
|
|
1592
|
+
let next: OptNodeOrNull<BinaryTreeNode<K, V>> = null;
|
|
1554
1593
|
while (node) {
|
|
1555
1594
|
next = node.right;
|
|
1556
1595
|
node.right = pre;
|
|
@@ -1559,9 +1598,9 @@ export class BinaryTree<
|
|
|
1559
1598
|
}
|
|
1560
1599
|
return pre;
|
|
1561
1600
|
};
|
|
1562
|
-
const _printEdge = (node: OptNodeOrNull<
|
|
1563
|
-
const tail: OptNodeOrNull<
|
|
1564
|
-
let cur: OptNodeOrNull<
|
|
1601
|
+
const _printEdge = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => {
|
|
1602
|
+
const tail: OptNodeOrNull<BinaryTreeNode<K, V>> = _reverseEdge(node);
|
|
1603
|
+
let cur: OptNodeOrNull<BinaryTreeNode<K, V>> = tail;
|
|
1565
1604
|
while (cur) {
|
|
1566
1605
|
ans.push(callback(cur));
|
|
1567
1606
|
cur = cur.right;
|
|
@@ -1635,8 +1674,13 @@ export class BinaryTree<
|
|
|
1635
1674
|
* original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in
|
|
1636
1675
|
* the original tree is null, a null node is added to the cloned tree. If a node
|
|
1637
1676
|
*/
|
|
1638
|
-
clone()
|
|
1677
|
+
clone() {
|
|
1639
1678
|
const cloned = this.createTree();
|
|
1679
|
+
this._clone(cloned);
|
|
1680
|
+
return cloned;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {
|
|
1640
1684
|
this.bfs(
|
|
1641
1685
|
node => {
|
|
1642
1686
|
if (node === null) cloned.add(null);
|
|
@@ -1650,7 +1694,6 @@ export class BinaryTree<
|
|
|
1650
1694
|
true
|
|
1651
1695
|
);
|
|
1652
1696
|
if (this._isMapMode) cloned._store = this._store;
|
|
1653
|
-
return cloned;
|
|
1654
1697
|
}
|
|
1655
1698
|
|
|
1656
1699
|
/**
|
|
@@ -1673,7 +1716,7 @@ export class BinaryTree<
|
|
|
1673
1716
|
const newTree = this.createTree();
|
|
1674
1717
|
let index = 0;
|
|
1675
1718
|
for (const [key, value] of this) {
|
|
1676
|
-
if (predicate.call(thisArg,
|
|
1719
|
+
if (predicate.call(thisArg, key, value, index++, this)) {
|
|
1677
1720
|
newTree.add([key, value]);
|
|
1678
1721
|
}
|
|
1679
1722
|
}
|
|
@@ -1684,43 +1727,41 @@ export class BinaryTree<
|
|
|
1684
1727
|
* Time Complexity: O(n)
|
|
1685
1728
|
* Space Complexity: O(n)
|
|
1686
1729
|
*
|
|
1687
|
-
* The `map` function
|
|
1688
|
-
*
|
|
1689
|
-
* @param callback -
|
|
1690
|
-
*
|
|
1691
|
-
*
|
|
1692
|
-
*
|
|
1693
|
-
*
|
|
1694
|
-
*
|
|
1695
|
-
*
|
|
1696
|
-
*
|
|
1730
|
+
* The `map` function in TypeScript creates a new BinaryTree by applying a callback function to each
|
|
1731
|
+
* entry in the original BinaryTree.
|
|
1732
|
+
* @param callback - A function that will be called for each entry in the current binary tree. It
|
|
1733
|
+
* takes the key, value (which can be undefined), and an array containing the mapped key and value as
|
|
1734
|
+
* arguments.
|
|
1735
|
+
* @param [options] - The `options` parameter in the `map` method is of type `BinaryTreeOptions<MK,
|
|
1736
|
+
* MV, MR>`. It is an optional parameter that allows you to specify additional options for the binary
|
|
1737
|
+
* tree being created during the mapping process. These options could include things like custom
|
|
1738
|
+
* comparators, initial
|
|
1739
|
+
* @param {any} [thisArg] - The `thisArg` parameter in the `map` method is used to specify the value
|
|
1740
|
+
* of `this` when executing the `callback` function. It allows you to set the context (value of
|
|
1741
|
+
* `this`) within the callback function. If `thisArg` is provided, it will be passed
|
|
1742
|
+
* @returns The `map` function is returning a new `BinaryTree` instance filled with entries that are
|
|
1743
|
+
* the result of applying the provided `callback` function to each entry in the original tree.
|
|
1697
1744
|
*/
|
|
1698
|
-
map(
|
|
1699
|
-
|
|
1745
|
+
map(
|
|
1746
|
+
callback: EntryCallback<K, V | undefined, [MK, MV]>,
|
|
1747
|
+
options?: BinaryTreeOptions<MK, MV, MR>,
|
|
1748
|
+
thisArg?: any
|
|
1749
|
+
): BinaryTree<MK, MV, MR> {
|
|
1750
|
+
const newTree = new BinaryTree<MK, MV, MR>([], options);
|
|
1700
1751
|
let index = 0;
|
|
1701
1752
|
for (const [key, value] of this) {
|
|
1702
|
-
newTree.add(
|
|
1753
|
+
newTree.add(callback.call(thisArg, key, value, index++, this));
|
|
1703
1754
|
}
|
|
1704
1755
|
return newTree;
|
|
1705
1756
|
}
|
|
1706
1757
|
|
|
1707
|
-
// // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
|
1708
|
-
// // map<NV>(callback: (entry: [K, V | undefined], tree: this) => NV) {
|
|
1709
|
-
// // const newTree = this.createTree();
|
|
1710
|
-
// // for (const [key, value] of this) {
|
|
1711
|
-
// // newTree.add(key, callback([key, value], this));
|
|
1712
|
-
// // }
|
|
1713
|
-
// // return newTree;
|
|
1714
|
-
// // }
|
|
1715
|
-
//
|
|
1716
|
-
|
|
1717
1758
|
/**
|
|
1718
1759
|
* Time Complexity: O(n)
|
|
1719
1760
|
* Space Complexity: O(n)
|
|
1720
1761
|
*
|
|
1721
1762
|
* The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
|
|
1722
1763
|
* customizable options for displaying undefined, null, and sentinel nodes.
|
|
1723
|
-
* @param {BTNRep<K, V,
|
|
1764
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1724
1765
|
* `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
|
|
1725
1766
|
* It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
|
|
1726
1767
|
* the default is set to the root
|
|
@@ -1732,7 +1773,10 @@ export class BinaryTree<
|
|
|
1732
1773
|
* the lines to the output string. The final output string contains the visual representation of the
|
|
1733
1774
|
* binary tree with the specified options.
|
|
1734
1775
|
*/
|
|
1735
|
-
override toVisual(
|
|
1776
|
+
override toVisual(
|
|
1777
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1778
|
+
options?: BinaryTreePrintOptions
|
|
1779
|
+
): string {
|
|
1736
1780
|
const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
|
|
1737
1781
|
startNode = this.ensureNode(startNode);
|
|
1738
1782
|
let output = '';
|
|
@@ -1742,8 +1786,8 @@ export class BinaryTree<
|
|
|
1742
1786
|
if (opts.isShowNull) output += `N for null\n`;
|
|
1743
1787
|
if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`;
|
|
1744
1788
|
|
|
1745
|
-
const display = (root: OptNodeOrNull<
|
|
1746
|
-
const [lines
|
|
1789
|
+
const display = (root: OptNodeOrNull<BinaryTreeNode<K, V>>): void => {
|
|
1790
|
+
const [lines] = this._displayAux(root, opts);
|
|
1747
1791
|
let paragraph = '';
|
|
1748
1792
|
for (const line of lines) {
|
|
1749
1793
|
paragraph += line + '\n';
|
|
@@ -1765,15 +1809,53 @@ export class BinaryTree<
|
|
|
1765
1809
|
* printing options for the binary tree. It is an optional parameter that allows you to customize how
|
|
1766
1810
|
* the binary tree is printed, such as choosing between different traversal orders or formatting
|
|
1767
1811
|
* options.
|
|
1768
|
-
* @param {BTNRep<K, V,
|
|
1812
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1769
1813
|
* `override print` method is used to specify the starting point for printing the binary tree. It can
|
|
1770
1814
|
* be either a key, a node, an entry, or the root of the tree. If no specific starting point is
|
|
1771
1815
|
* provided, the default value is set to
|
|
1772
1816
|
*/
|
|
1773
|
-
override print(options?: BinaryTreePrintOptions, startNode: BTNRep<K, V,
|
|
1817
|
+
override print(options?: BinaryTreePrintOptions, startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root) {
|
|
1774
1818
|
console.log(this.toVisual(startNode, options));
|
|
1775
1819
|
}
|
|
1776
1820
|
|
|
1821
|
+
/**
|
|
1822
|
+
* Time Complexity: O(1)
|
|
1823
|
+
* Space Complexity: O(1)
|
|
1824
|
+
*
|
|
1825
|
+
* The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
|
|
1826
|
+
* or returns null.
|
|
1827
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The
|
|
1828
|
+
* `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeOrEntry`, which
|
|
1829
|
+
* can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. This parameter represents either a key, a
|
|
1830
|
+
* node, an entry
|
|
1831
|
+
* @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
|
|
1832
|
+
* an optional parameter of type `V`. It represents the value associated with the key in the node
|
|
1833
|
+
* being created. If a `value` is provided, it will be used when creating the node. If
|
|
1834
|
+
* @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
|
|
1835
|
+
* (`OptNodeOrNull<BinaryTreeNode<K, V>>`) based on the input parameters provided. The function checks the type of the
|
|
1836
|
+
* input parameter (`keyNodeOrEntry`) and processes it accordingly to return a node or null
|
|
1837
|
+
* value.
|
|
1838
|
+
*/
|
|
1839
|
+
protected _keyValueNodeOrEntryToNodeAndValue(
|
|
1840
|
+
keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1841
|
+
value?: V
|
|
1842
|
+
): [OptNodeOrNull<BinaryTreeNode<K, V>>, V | undefined] {
|
|
1843
|
+
if (keyNodeOrEntry === undefined) return [undefined, undefined];
|
|
1844
|
+
if (keyNodeOrEntry === null) return [null, undefined];
|
|
1845
|
+
|
|
1846
|
+
if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];
|
|
1847
|
+
|
|
1848
|
+
if (this.isEntry(keyNodeOrEntry)) {
|
|
1849
|
+
const [key, entryValue] = keyNodeOrEntry;
|
|
1850
|
+
if (key === undefined) return [undefined, undefined];
|
|
1851
|
+
else if (key === null) return [null, undefined];
|
|
1852
|
+
const finalValue = value ?? entryValue;
|
|
1853
|
+
return [this.createNode(key, finalValue), finalValue];
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
return [this.createNode(keyNodeOrEntry, value), value];
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1777
1859
|
/**
|
|
1778
1860
|
* Time complexity: O(n)
|
|
1779
1861
|
* Space complexity: O(n)
|
|
@@ -1782,11 +1864,11 @@ export class BinaryTree<
|
|
|
1782
1864
|
* the specified order pattern and callback function.
|
|
1783
1865
|
* @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
|
|
1784
1866
|
* called on each node visited during the depth-first search traversal. It is of type `C`, which
|
|
1785
|
-
* extends `NodeCallback<OptNodeOrNull<
|
|
1867
|
+
* extends `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`. The default value for this parameter is `this._DEFAULT
|
|
1786
1868
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1787
1869
|
* order in which the nodes are visited during the Depth-First Search traversal. It can have one of
|
|
1788
1870
|
* the following values:
|
|
1789
|
-
* @param {BTNRep<K, V,
|
|
1871
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `_dfs`
|
|
1790
1872
|
* method is used to specify the starting point for the depth-first search traversal in a binary
|
|
1791
1873
|
* tree. It can be provided as either a `BTNRep` object or a reference to the root node
|
|
1792
1874
|
* of the tree. If no specific
|
|
@@ -1816,26 +1898,26 @@ export class BinaryTree<
|
|
|
1816
1898
|
* @returns The function `_dfs` returns an array of the return type of the callback function provided
|
|
1817
1899
|
* as input.
|
|
1818
1900
|
*/
|
|
1819
|
-
protected _dfs<C extends NodeCallback<OptNodeOrNull<
|
|
1901
|
+
protected _dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1820
1902
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1821
1903
|
pattern: DFSOrderPattern = 'IN',
|
|
1822
|
-
startNode: BTNRep<K, V,
|
|
1904
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1823
1905
|
iterationType: IterationType = this.iterationType,
|
|
1824
1906
|
includeNull = false,
|
|
1825
|
-
shouldVisitLeft: (node: OptNodeOrNull<
|
|
1826
|
-
shouldVisitRight: (node: OptNodeOrNull<
|
|
1827
|
-
shouldVisitRoot: (node: OptNodeOrNull<
|
|
1907
|
+
shouldVisitLeft: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => !!node,
|
|
1908
|
+
shouldVisitRight: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => !!node,
|
|
1909
|
+
shouldVisitRoot: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => {
|
|
1828
1910
|
if (includeNull) return this.isRealNodeOrNull(node);
|
|
1829
1911
|
return this.isRealNode(node);
|
|
1830
1912
|
},
|
|
1831
|
-
shouldProcessRoot: (node: OptNodeOrNull<
|
|
1913
|
+
shouldProcessRoot: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => this.isRealNodeOrNull(node)
|
|
1832
1914
|
): ReturnType<C>[] {
|
|
1833
1915
|
startNode = this.ensureNode(startNode);
|
|
1834
1916
|
if (!startNode) return [];
|
|
1835
1917
|
const ans: ReturnType<C>[] = [];
|
|
1836
1918
|
|
|
1837
1919
|
if (iterationType === 'RECURSIVE') {
|
|
1838
|
-
const dfs = (node: OptNodeOrNull<
|
|
1920
|
+
const dfs = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => {
|
|
1839
1921
|
if (!shouldVisitRoot(node)) return;
|
|
1840
1922
|
|
|
1841
1923
|
const visitLeft = () => {
|
|
@@ -1866,15 +1948,15 @@ export class BinaryTree<
|
|
|
1866
1948
|
|
|
1867
1949
|
dfs(startNode);
|
|
1868
1950
|
} else {
|
|
1869
|
-
const stack: DFSStackItem<
|
|
1951
|
+
const stack: DFSStackItem<BinaryTreeNode<K, V>>[] = [{ opt: DFSOperation.VISIT, node: startNode }];
|
|
1870
1952
|
|
|
1871
|
-
const pushLeft = (cur: DFSStackItem<
|
|
1953
|
+
const pushLeft = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {
|
|
1872
1954
|
if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
|
|
1873
1955
|
};
|
|
1874
|
-
const pushRight = (cur: DFSStackItem<
|
|
1956
|
+
const pushRight = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {
|
|
1875
1957
|
if (shouldVisitRight(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });
|
|
1876
1958
|
};
|
|
1877
|
-
const pushRoot = (cur: DFSStackItem<
|
|
1959
|
+
const pushRoot = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {
|
|
1878
1960
|
if (shouldVisitRoot(cur.node)) stack.push({ opt: DFSOperation.PROCESS, node: cur.node });
|
|
1879
1961
|
};
|
|
1880
1962
|
|
|
@@ -1928,8 +2010,8 @@ export class BinaryTree<
|
|
|
1928
2010
|
if (!node) return;
|
|
1929
2011
|
|
|
1930
2012
|
if (this.iterationType === 'ITERATIVE') {
|
|
1931
|
-
const stack: OptNodeOrNull<
|
|
1932
|
-
let current: OptNodeOrNull<
|
|
2013
|
+
const stack: OptNodeOrNull<BinaryTreeNode<K, V>>[] = [];
|
|
2014
|
+
let current: OptNodeOrNull<BinaryTreeNode<K, V>> = node;
|
|
1933
2015
|
|
|
1934
2016
|
while (current || stack.length > 0) {
|
|
1935
2017
|
while (this.isRealNode(current)) {
|
|
@@ -1972,7 +2054,7 @@ export class BinaryTree<
|
|
|
1972
2054
|
* information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
|
|
1973
2055
|
* elements:
|
|
1974
2056
|
*/
|
|
1975
|
-
protected _displayAux(node: OptNodeOrNull<
|
|
2057
|
+
protected _displayAux(node: OptNodeOrNull<BinaryTreeNode<K, V>>, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
|
1976
2058
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1977
2059
|
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
1978
2060
|
|
|
@@ -2040,24 +2122,27 @@ export class BinaryTree<
|
|
|
2040
2122
|
}
|
|
2041
2123
|
}
|
|
2042
2124
|
|
|
2043
|
-
protected _DEFAULT_NODE_CALLBACK = (node: OptNodeOrNull<
|
|
2125
|
+
protected _DEFAULT_NODE_CALLBACK = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => (node ? node.key : undefined);
|
|
2044
2126
|
|
|
2045
2127
|
/**
|
|
2046
2128
|
* Time Complexity: O(1)
|
|
2047
2129
|
* Space Complexity: O(1)
|
|
2048
2130
|
*
|
|
2049
2131
|
* The _swapProperties function swaps key and value properties between two nodes in a binary tree.
|
|
2050
|
-
* @param {BTNRep<K, V,
|
|
2132
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} srcNode - The `srcNode` parameter in the
|
|
2051
2133
|
* `_swapProperties` method can be either a BTNRep object containing key and value
|
|
2052
2134
|
* properties, or it can be of type R.
|
|
2053
|
-
* @param {BTNRep<K, V,
|
|
2135
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} destNode - The `destNode` parameter in the
|
|
2054
2136
|
* `_swapProperties` method represents the node or entry where the properties will be swapped with
|
|
2055
|
-
* the `srcNode`. It can be of type `BTNRep<K, V,
|
|
2137
|
+
* the `srcNode`. It can be of type `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`. The method ensures that
|
|
2056
2138
|
* both `srcNode
|
|
2057
2139
|
* @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
|
|
2058
2140
|
* with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
|
|
2059
2141
|
*/
|
|
2060
|
-
protected _swapProperties(
|
|
2142
|
+
protected _swapProperties(
|
|
2143
|
+
srcNode: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
2144
|
+
destNode: BTNRep<K, V, BinaryTreeNode<K, V>>
|
|
2145
|
+
): BinaryTreeNode<K, V> | undefined {
|
|
2061
2146
|
srcNode = this.ensureNode(srcNode);
|
|
2062
2147
|
destNode = this.ensureNode(destNode);
|
|
2063
2148
|
|
|
@@ -2083,16 +2168,16 @@ export class BinaryTree<
|
|
|
2083
2168
|
* Space Complexity: O(1)
|
|
2084
2169
|
*
|
|
2085
2170
|
* The _replaceNode function replaces an old node with a new node in a binary tree structure.
|
|
2086
|
-
* @param {
|
|
2171
|
+
* @param {BinaryTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that you want to replace in a
|
|
2087
2172
|
* tree data structure.
|
|
2088
|
-
* @param {
|
|
2173
|
+
* @param {BinaryTreeNode<K, V>} newNode - The `newNode` parameter in the `_replaceNode` function represents the node
|
|
2089
2174
|
* that will replace the `oldNode` in a tree data structure. This function is responsible for
|
|
2090
2175
|
* updating the parent, left child, right child, and root (if necessary) references when replacing a
|
|
2091
2176
|
* node in the tree.
|
|
2092
2177
|
* @returns The method `_replaceNode` is returning the `newNode` that was passed as a parameter after
|
|
2093
2178
|
* replacing the `oldNode` with it in the binary tree structure.
|
|
2094
2179
|
*/
|
|
2095
|
-
protected _replaceNode(oldNode:
|
|
2180
|
+
protected _replaceNode(oldNode: BinaryTreeNode<K, V>, newNode: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
|
|
2096
2181
|
if (oldNode.parent) {
|
|
2097
2182
|
if (oldNode.parent.left === oldNode) {
|
|
2098
2183
|
oldNode.parent.left = newNode;
|
|
@@ -2116,10 +2201,10 @@ export class BinaryTree<
|
|
|
2116
2201
|
*
|
|
2117
2202
|
* The function _setRoot sets the root node of a data structure while updating the parent reference
|
|
2118
2203
|
* of the previous root node.
|
|
2119
|
-
* @param v - The parameter `v` in the `_setRoot` method is of type `OptNodeOrNull<
|
|
2120
|
-
* it can either be an optional `
|
|
2204
|
+
* @param v - The parameter `v` in the `_setRoot` method is of type `OptNodeOrNull<BinaryTreeNode<K, V>>`, which means
|
|
2205
|
+
* it can either be an optional `BinaryTreeNode<K, V>` type or `null`.
|
|
2121
2206
|
*/
|
|
2122
|
-
protected _setRoot(v: OptNodeOrNull<
|
|
2207
|
+
protected _setRoot(v: OptNodeOrNull<BinaryTreeNode<K, V>>) {
|
|
2123
2208
|
if (v) {
|
|
2124
2209
|
v.parent = undefined;
|
|
2125
2210
|
}
|
|
@@ -2132,34 +2217,29 @@ export class BinaryTree<
|
|
|
2132
2217
|
*
|
|
2133
2218
|
* The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
|
|
2134
2219
|
* predicate function for a binary tree node.
|
|
2135
|
-
* @param {BTNRep<K, V,
|
|
2220
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
|
|
2136
2221
|
* `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
|
|
2137
|
-
* parameter `
|
|
2222
|
+
* parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be
|
|
2138
2223
|
* used for filtering nodes in a binary tree.
|
|
2139
|
-
* @returns A NodePredicate<
|
|
2224
|
+
* @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.
|
|
2140
2225
|
*/
|
|
2141
2226
|
protected _ensurePredicate(
|
|
2142
|
-
|
|
2143
|
-
): NodePredicate<
|
|
2144
|
-
if (
|
|
2145
|
-
return (node:
|
|
2227
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>
|
|
2228
|
+
): NodePredicate<BinaryTreeNode<K, V>> {
|
|
2229
|
+
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined)
|
|
2230
|
+
return (node: BinaryTreeNode<K, V>) => (node ? false : false);
|
|
2146
2231
|
|
|
2147
|
-
if (this._isPredicate(
|
|
2232
|
+
if (this._isPredicate(keyNodeEntryOrPredicate)) return keyNodeEntryOrPredicate;
|
|
2148
2233
|
|
|
2149
|
-
if (this.isRealNode(
|
|
2234
|
+
if (this.isRealNode(keyNodeEntryOrPredicate))
|
|
2235
|
+
return (node: BinaryTreeNode<K, V>) => node === keyNodeEntryOrPredicate;
|
|
2150
2236
|
|
|
2151
|
-
if (this.isEntry(
|
|
2152
|
-
const [key] =
|
|
2153
|
-
return (node:
|
|
2237
|
+
if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
2238
|
+
const [key] = keyNodeEntryOrPredicate;
|
|
2239
|
+
return (node: BinaryTreeNode<K, V>) => node.key === key;
|
|
2154
2240
|
}
|
|
2155
2241
|
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
if (this._toEntryFn) {
|
|
2159
|
-
const [key] = this._toEntryFn(keyNodeEntryRawOrPredicate);
|
|
2160
|
-
return (node: NODE) => node.key === key;
|
|
2161
|
-
}
|
|
2162
|
-
return (node: NODE) => node.key === keyNodeEntryRawOrPredicate;
|
|
2242
|
+
return (node: BinaryTreeNode<K, V>) => node.key === keyNodeEntryOrPredicate;
|
|
2163
2243
|
}
|
|
2164
2244
|
|
|
2165
2245
|
/**
|
|
@@ -2169,12 +2249,12 @@ export class BinaryTree<
|
|
|
2169
2249
|
* The function `_isPredicate` checks if a given parameter is a function.
|
|
2170
2250
|
* @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type
|
|
2171
2251
|
* of value. In this context, the function `_isPredicate` is checking if `p` is a function that
|
|
2172
|
-
* satisfies the type `NodePredicate<
|
|
2252
|
+
* satisfies the type `NodePredicate<BinaryTreeNode<K, V>>`.
|
|
2173
2253
|
* @returns The function is checking if the input `p` is a function and returning a boolean value
|
|
2174
2254
|
* based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
|
|
2175
2255
|
* predicate function for a binary tree node. If `p` is not a function, it will return `false`.
|
|
2176
2256
|
*/
|
|
2177
|
-
protected _isPredicate(p: any): p is NodePredicate<
|
|
2257
|
+
protected _isPredicate(p: any): p is NodePredicate<BinaryTreeNode<K, V>> {
|
|
2178
2258
|
return typeof p === 'function';
|
|
2179
2259
|
}
|
|
2180
2260
|
|
|
@@ -2184,30 +2264,22 @@ export class BinaryTree<
|
|
|
2184
2264
|
*
|
|
2185
2265
|
* The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,
|
|
2186
2266
|
* entry, raw data, or null/undefined.
|
|
2187
|
-
* @param {BTNRep<K, V,
|
|
2188
|
-
* TypeScript method that takes in a parameter `
|
|
2189
|
-
* where `BTNRep` is a generic type with keys `K`, `V`, and `
|
|
2190
|
-
* @returns The `_extractKey` method returns the key value extracted from the `
|
|
2267
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry - The `_extractKey` method you provided is a
|
|
2268
|
+
* TypeScript method that takes in a parameter `keyNodeOrEntry` of type `BTNRep<K, V, BinaryTreeNode<K, V>>`,
|
|
2269
|
+
* where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `
|
|
2270
|
+
* @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`
|
|
2191
2271
|
* parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
|
|
2192
2272
|
* the conditions checked in the method.
|
|
2193
2273
|
*/
|
|
2194
|
-
protected _extractKey(
|
|
2195
|
-
if (
|
|
2196
|
-
if (
|
|
2197
|
-
if (
|
|
2198
|
-
if (this.isNode(
|
|
2199
|
-
|
|
2200
|
-
if (this.isEntry(
|
|
2201
|
-
|
|
2202
|
-
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
2203
|
-
if (this._toEntryFn) {
|
|
2204
|
-
const [key] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
2205
|
-
return key;
|
|
2206
|
-
}
|
|
2207
|
-
return;
|
|
2208
|
-
}
|
|
2274
|
+
protected _extractKey(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): K | null | undefined {
|
|
2275
|
+
if (keyNodeOrEntry === null) return null;
|
|
2276
|
+
if (keyNodeOrEntry === undefined) return;
|
|
2277
|
+
if (keyNodeOrEntry === this._NIL) return;
|
|
2278
|
+
if (this.isNode(keyNodeOrEntry)) return keyNodeOrEntry.key;
|
|
2279
|
+
|
|
2280
|
+
if (this.isEntry(keyNodeOrEntry)) return keyNodeOrEntry[0];
|
|
2209
2281
|
|
|
2210
|
-
return
|
|
2282
|
+
return keyNodeOrEntry;
|
|
2211
2283
|
}
|
|
2212
2284
|
|
|
2213
2285
|
/**
|