red-black-tree-typed 1.53.6 → 1.54.1
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/README.md +52 -0
- package/dist/common/index.d.ts +12 -0
- package/dist/common/index.js +28 -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 -331
- package/dist/data-structures/binary-tree/avl-tree.d.ts +103 -69
- package/dist/data-structures/binary-tree/avl-tree.js +131 -71
- 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 +309 -208
- package/dist/data-structures/binary-tree/binary-tree.js +382 -300
- package/dist/data-structures/binary-tree/bst.d.ts +245 -127
- package/dist/data-structures/binary-tree/bst.js +366 -163
- 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} +181 -108
- 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 +26 -9
- package/dist/data-structures/heap/heap.js +37 -17
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +64 -19
- package/dist/data-structures/linked-list/doubly-linked-list.js +92 -31
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +48 -12
- package/dist/data-structures/linked-list/singly-linked-list.js +74 -27
- 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 +111 -10
- package/dist/data-structures/trie/trie.js +123 -18
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- 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-counter.js +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 +1 -4
- package/dist/types/data-structures/binary-tree/bst.d.ts +6 -5
- package/dist/types/data-structures/binary-tree/index.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/index.js +2 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -5
- 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/dist/types/utils/utils.d.ts +10 -6
- package/dist/utils/utils.js +4 -2
- package/package.json +2 -2
- package/src/common/index.ts +25 -0
- 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 +152 -373
- package/src/data-structures/binary-tree/avl-tree.ts +164 -106
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-tree.ts +563 -447
- package/src/data-structures/binary-tree/bst.ts +433 -237
- package/src/data-structures/binary-tree/index.ts +3 -1
- package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +224 -146
- 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 +72 -49
- package/src/data-structures/linked-list/doubly-linked-list.ts +186 -118
- package/src/data-structures/linked-list/singly-linked-list.ts +81 -28
- 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 +123 -17
- package/src/index.ts +4 -3
- 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 +1 -6
- package/src/types/data-structures/binary-tree/bst.ts +8 -7
- 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/src/types/utils/utils.ts +16 -10
- package/src/utils/utils.ts +4 -2
- package/dist/data-structures/binary-tree/rb-tree.d.ts +0 -205
- package/src/types/data-structures/binary-tree/rb-tree.ts +0 -10
|
@@ -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,70 +21,104 @@ 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';
|
|
29
28
|
import { isComparable, trampoline } from '../../utils';
|
|
30
29
|
import { Queue } from '../queue';
|
|
31
30
|
import { IterableEntryBase } from '../base';
|
|
32
|
-
import { DFSOperation } from '../../
|
|
31
|
+
import { DFSOperation, Range } from '../../common';
|
|
33
32
|
|
|
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;
|
|
55
|
+
|
|
56
|
+
parent?: BinaryTreeNode<K, V> = undefined;
|
|
56
57
|
|
|
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,59 +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.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value), value];
|
|
237
|
-
|
|
238
|
-
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
239
|
-
if (this._toEntryFn) {
|
|
240
|
-
const [key, entryValue] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
241
|
-
const finalValue = value ?? entryValue;
|
|
242
|
-
if (this.isKey(key)) return [this.createNode(key, finalValue), finalValue];
|
|
243
|
-
}
|
|
244
|
-
return [undefined, undefined];
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
return [undefined, undefined];
|
|
236
|
+
});
|
|
248
237
|
}
|
|
249
238
|
|
|
250
239
|
/**
|
|
@@ -253,8 +242,8 @@ export class BinaryTree<
|
|
|
253
242
|
*
|
|
254
243
|
* The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
|
|
255
244
|
* value and returns the corresponding node or null.
|
|
256
|
-
* @param {BTNRep<K, V,
|
|
257
|
-
* 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
|
|
258
247
|
* is used to determine whether the input is a key, node, entry, or raw data. The
|
|
259
248
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
|
|
260
249
|
* is used to specify the type of iteration to be performed. It has a default value of
|
|
@@ -263,131 +252,174 @@ export class BinaryTree<
|
|
|
263
252
|
* conditions specified in the code snippet.
|
|
264
253
|
*/
|
|
265
254
|
ensureNode(
|
|
266
|
-
|
|
255
|
+
keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
267
256
|
iterationType: IterationType = this.iterationType
|
|
268
|
-
): OptNodeOrNull<
|
|
269
|
-
if (
|
|
270
|
-
if (
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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];
|
|
276
266
|
if (key === null) return null;
|
|
277
267
|
if (key === undefined) return;
|
|
278
|
-
return this.
|
|
268
|
+
return this.getNode(key, this._root, iterationType);
|
|
279
269
|
}
|
|
280
270
|
|
|
281
|
-
|
|
282
|
-
const [key] = this._toEntryFn(keyNodeEntryOrRaw as R);
|
|
283
|
-
if (this.isKey(key)) return this.getNodeByKey(key);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (this.isKey(keyNodeEntryOrRaw)) return this.getNodeByKey(keyNodeEntryOrRaw, iterationType);
|
|
287
|
-
return;
|
|
271
|
+
return this.getNode(keyNodeOrEntry, this._root, iterationType);
|
|
288
272
|
}
|
|
289
273
|
|
|
290
274
|
/**
|
|
275
|
+
* Time Complexity: O(1)
|
|
276
|
+
* Space Complexity: O(1)
|
|
277
|
+
*
|
|
291
278
|
* The function isNode checks if the input is an instance of BinaryTreeNode.
|
|
292
|
-
* @param {BTNRep<K, V,
|
|
293
|
-
* `
|
|
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
|
|
294
281
|
* checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
|
|
295
282
|
* accordingly.
|
|
296
|
-
* @returns The function `isNode` is checking if the input `
|
|
283
|
+
* @returns The function `isNode` is checking if the input `keyNodeOrEntry` is an instance of
|
|
297
284
|
* `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If
|
|
298
285
|
* it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
|
|
299
286
|
* is not a node.
|
|
300
287
|
*/
|
|
301
|
-
isNode(
|
|
302
|
-
return
|
|
288
|
+
isNode(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> {
|
|
289
|
+
return keyNodeOrEntry instanceof BinaryTreeNode;
|
|
303
290
|
}
|
|
304
291
|
|
|
305
|
-
|
|
306
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Time Complexity: O(1)
|
|
294
|
+
* Space Complexity: O(1)
|
|
295
|
+
*
|
|
296
|
+
* The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.
|
|
297
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | R} keyNodeEntryOrRaw - BTNRep<K, V, BinaryTreeNode<K, V>>
|
|
298
|
+
* @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by
|
|
299
|
+
* checking if it is an object. If the parameter is an object, the function will return `true`,
|
|
300
|
+
* indicating that it is of type `R`.
|
|
301
|
+
*/
|
|
302
|
+
isRaw(keyNodeEntryOrRaw: BTNRep<K, V, BinaryTreeNode<K, V>> | R): keyNodeEntryOrRaw is R {
|
|
303
|
+
return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';
|
|
307
304
|
}
|
|
308
305
|
|
|
309
306
|
/**
|
|
307
|
+
* Time Complexity: O(1)
|
|
308
|
+
* Space Complexity: O(1)
|
|
309
|
+
*
|
|
310
310
|
* The function `isRealNode` checks if a given input is a valid node in a binary tree.
|
|
311
|
-
* @param {BTNRep<K, V,
|
|
312
|
-
* parameter in the `isRealNode` function can be of type `BTNRep<K, V,
|
|
313
|
-
* The function checks if the input parameter is a `
|
|
314
|
-
* @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
|
|
315
315
|
* node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
|
|
316
316
|
* values, it then calls the `isNode` method to further determine if the input is a node. The
|
|
317
317
|
* function will return a boolean value indicating whether the
|
|
318
318
|
*/
|
|
319
|
-
isRealNode(
|
|
320
|
-
if (
|
|
321
|
-
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);
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
/**
|
|
325
|
+
* Time Complexity: O(1)
|
|
326
|
+
* Space Complexity: O(1)
|
|
327
|
+
*
|
|
325
328
|
* The function checks if a given input is a valid node or null.
|
|
326
|
-
* @param {BTNRep<K, V,
|
|
327
|
-
* `
|
|
328
|
-
* 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
|
|
329
332
|
* @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
|
|
330
|
-
* `
|
|
333
|
+
* `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or
|
|
331
334
|
* `null`, and `false` otherwise.
|
|
332
335
|
*/
|
|
333
|
-
isRealNodeOrNull(
|
|
334
|
-
return
|
|
336
|
+
isRealNodeOrNull(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): keyNodeOrEntry is BinaryTreeNode<K, V> | null {
|
|
337
|
+
return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);
|
|
335
338
|
}
|
|
336
339
|
|
|
337
340
|
/**
|
|
341
|
+
* Time Complexity: O(1)
|
|
342
|
+
* Space Complexity: O(1)
|
|
343
|
+
*
|
|
338
344
|
* The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
|
|
339
|
-
* @param {BTNRep<K, V,
|
|
340
|
-
*
|
|
341
|
-
* @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`
|
|
342
348
|
* property of the current object and returning a boolean value based on that comparison.
|
|
343
349
|
*/
|
|
344
|
-
isNIL(
|
|
345
|
-
return
|
|
350
|
+
isNIL(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): boolean {
|
|
351
|
+
return keyNodeOrEntry === this._NIL;
|
|
352
|
+
}
|
|
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
|
+
*/
|
|
368
|
+
isRange(
|
|
369
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>> | Range<K>
|
|
370
|
+
): keyNodeEntryOrPredicate is Range<K> {
|
|
371
|
+
return keyNodeEntryOrPredicate instanceof Range;
|
|
346
372
|
}
|
|
347
373
|
|
|
348
374
|
/**
|
|
375
|
+
* Time Complexity: O(1)
|
|
376
|
+
* Space Complexity: O(1)
|
|
377
|
+
*
|
|
349
378
|
* The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
|
|
350
379
|
* tree.
|
|
351
|
-
* @param {BTNRep<K, V,
|
|
352
|
-
* `
|
|
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
|
|
353
382
|
* key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
|
|
354
383
|
* provided
|
|
355
384
|
* @returns The function `isLeaf` returns a boolean value indicating whether the input
|
|
356
|
-
* `
|
|
385
|
+
* `keyNodeOrEntry` is a leaf node in a binary tree.
|
|
357
386
|
*/
|
|
358
|
-
isLeaf(
|
|
359
|
-
|
|
360
|
-
if (
|
|
361
|
-
if (
|
|
362
|
-
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);
|
|
363
392
|
}
|
|
364
393
|
|
|
365
394
|
/**
|
|
395
|
+
* Time Complexity: O(1)
|
|
396
|
+
* Space Complexity: O(1)
|
|
397
|
+
*
|
|
366
398
|
* The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
|
|
367
399
|
* with a length of 2.
|
|
368
|
-
* @param {BTNRep<K, V,
|
|
369
|
-
* parameter in the `isEntry` function can be of type `BTNRep<K, V,
|
|
370
|
-
* The function checks if the provided `
|
|
371
|
-
* @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
|
|
372
404
|
* with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
|
|
373
405
|
* `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
|
|
374
406
|
*/
|
|
375
|
-
isEntry(
|
|
376
|
-
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;
|
|
377
409
|
}
|
|
378
410
|
|
|
379
411
|
/**
|
|
380
412
|
* Time Complexity O(1)
|
|
381
413
|
* Space Complexity O(1)
|
|
382
414
|
*
|
|
383
|
-
* The function `
|
|
415
|
+
* The function `isValidKey` checks if a given key is comparable.
|
|
384
416
|
* @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in
|
|
385
417
|
* TypeScript.
|
|
386
|
-
* @returns The function `
|
|
418
|
+
* @returns The function `isValidKey` is checking if the `key` parameter is `null` or if it is comparable.
|
|
387
419
|
* If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
|
|
388
420
|
* `isComparable` function, which is not provided in the code snippet.
|
|
389
421
|
*/
|
|
390
|
-
|
|
422
|
+
isValidKey(key: any): key is K {
|
|
391
423
|
if (key === null) return true;
|
|
392
424
|
return isComparable(key);
|
|
393
425
|
}
|
|
@@ -398,8 +430,8 @@ export class BinaryTree<
|
|
|
398
430
|
*
|
|
399
431
|
* The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
|
|
400
432
|
* and finding the correct insertion position.
|
|
401
|
-
* @param {BTNRep<K, V,
|
|
402
|
-
* 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`
|
|
403
435
|
* parameter in the method can accept different types of values:
|
|
404
436
|
* @param {V} [value] - The `value` parameter in the `add` method represents the value associated
|
|
405
437
|
* with the key that you want to add to the binary tree. When adding a key-value pair to the binary
|
|
@@ -409,8 +441,8 @@ export class BinaryTree<
|
|
|
409
441
|
* node was successful, and `false` if the insertion position could not be found or if a duplicate
|
|
410
442
|
* key was found and the node was replaced instead of inserted.
|
|
411
443
|
*/
|
|
412
|
-
add(
|
|
413
|
-
const [newNode, newValue] = this.
|
|
444
|
+
add(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>, value?: V): boolean {
|
|
445
|
+
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
414
446
|
if (newNode === undefined) return false;
|
|
415
447
|
|
|
416
448
|
// If the tree is empty, directly set the new node as the root node
|
|
@@ -421,8 +453,8 @@ export class BinaryTree<
|
|
|
421
453
|
return true;
|
|
422
454
|
}
|
|
423
455
|
|
|
424
|
-
const queue = new Queue<
|
|
425
|
-
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
|
|
426
458
|
|
|
427
459
|
while (queue.size > 0) {
|
|
428
460
|
const cur = queue.shift();
|
|
@@ -467,14 +499,14 @@ export class BinaryTree<
|
|
|
467
499
|
|
|
468
500
|
/**
|
|
469
501
|
* Time Complexity: O(k * n)
|
|
470
|
-
* Space Complexity: O(
|
|
502
|
+
* Space Complexity: O(k)
|
|
471
503
|
*
|
|
472
504
|
* The `addMany` function takes in multiple keys or nodes or entries or raw values along with
|
|
473
505
|
* optional values, and adds them to a data structure while returning an array indicating whether
|
|
474
506
|
* each insertion was successful.
|
|
475
507
|
* @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
|
|
476
508
|
* mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
|
|
477
|
-
* `BTNRep<K, V,
|
|
509
|
+
* `BTNRep<K, V, BinaryTreeNode<K, V>>` or `R`.
|
|
478
510
|
* @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
|
|
479
511
|
* accepts an iterable of values. These values correspond to the keys or nodes being added in the
|
|
480
512
|
* `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
|
|
@@ -483,7 +515,10 @@ export class BinaryTree<
|
|
|
483
515
|
* node, entry, or raw value was successfully added to the data structure. Each boolean value
|
|
484
516
|
* corresponds to the success of adding the corresponding key or value in the input iterable.
|
|
485
517
|
*/
|
|
486
|
-
addMany(
|
|
518
|
+
addMany(
|
|
519
|
+
keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R>,
|
|
520
|
+
values?: Iterable<V | undefined>
|
|
521
|
+
): boolean[] {
|
|
487
522
|
// TODO not sure addMany not be run multi times
|
|
488
523
|
const inserted: boolean[] = [];
|
|
489
524
|
|
|
@@ -492,7 +527,7 @@ export class BinaryTree<
|
|
|
492
527
|
valuesIterator = values[Symbol.iterator]();
|
|
493
528
|
}
|
|
494
529
|
|
|
495
|
-
for (
|
|
530
|
+
for (let keyNodeEntryOrRaw of keysNodesEntriesOrRaws) {
|
|
496
531
|
let value: V | undefined | null = undefined;
|
|
497
532
|
|
|
498
533
|
if (valuesIterator) {
|
|
@@ -501,13 +536,25 @@ export class BinaryTree<
|
|
|
501
536
|
value = valueResult.value;
|
|
502
537
|
}
|
|
503
538
|
}
|
|
504
|
-
|
|
539
|
+
if (this.isRaw(keyNodeEntryOrRaw)) keyNodeEntryOrRaw = this._toEntryFn!(keyNodeEntryOrRaw);
|
|
505
540
|
inserted.push(this.add(keyNodeEntryOrRaw, value));
|
|
506
541
|
}
|
|
507
542
|
|
|
508
543
|
return inserted;
|
|
509
544
|
}
|
|
510
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Time Complexity: O(k * n)
|
|
548
|
+
* Space Complexity: O(1)
|
|
549
|
+
*
|
|
550
|
+
* The `merge` function in TypeScript merges another binary tree into the current tree by adding all
|
|
551
|
+
* elements from the other tree.
|
|
552
|
+
* @param anotherTree - BinaryTree<K, V, R, MK, MV, MR>
|
|
553
|
+
*/
|
|
554
|
+
merge(anotherTree: BinaryTree<K, V, R, MK, MV, MR>) {
|
|
555
|
+
this.addMany(anotherTree, []);
|
|
556
|
+
}
|
|
557
|
+
|
|
511
558
|
/**
|
|
512
559
|
* Time Complexity: O(k * n)
|
|
513
560
|
* Space Complexity: O(1)
|
|
@@ -515,12 +562,15 @@ export class BinaryTree<
|
|
|
515
562
|
* The `refill` function clears the existing data structure and then adds new key-value pairs based
|
|
516
563
|
* on the provided input.
|
|
517
564
|
* @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
|
|
518
|
-
* 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`
|
|
519
566
|
* objects.
|
|
520
567
|
* @param [values] - The `values` parameter in the `refill` method is an optional parameter that
|
|
521
568
|
* accepts an iterable of values of type `V` or `undefined`.
|
|
522
569
|
*/
|
|
523
|
-
refill(
|
|
570
|
+
refill(
|
|
571
|
+
keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>> | R>,
|
|
572
|
+
values?: Iterable<V | undefined>
|
|
573
|
+
): void {
|
|
524
574
|
this.clear();
|
|
525
575
|
this.addMany(keysNodesEntriesOrRaws, values);
|
|
526
576
|
}
|
|
@@ -531,7 +581,7 @@ export class BinaryTree<
|
|
|
531
581
|
*
|
|
532
582
|
* The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
|
|
533
583
|
* the deleted node along with information for tree balancing.
|
|
534
|
-
* @param {BTNRep<K, V,
|
|
584
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} keyNodeOrEntry
|
|
535
585
|
* - The `delete` method you provided is used to delete a node from a binary tree based on the key,
|
|
536
586
|
* node, entry or raw data. The method returns an array of
|
|
537
587
|
* `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
|
|
@@ -540,16 +590,16 @@ export class BinaryTree<
|
|
|
540
590
|
* the array contains information about the node that was deleted (`deleted`) and the node that may
|
|
541
591
|
* need to be balanced (`needBalanced`).
|
|
542
592
|
*/
|
|
543
|
-
delete(
|
|
544
|
-
const deletedResult: BinaryTreeDeleteResult<
|
|
593
|
+
delete(keyNodeOrEntry: BTNRep<K, V, BinaryTreeNode<K, V>>): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {
|
|
594
|
+
const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];
|
|
545
595
|
if (!this._root) return deletedResult;
|
|
546
596
|
|
|
547
|
-
const curr = this.getNode(
|
|
597
|
+
const curr = this.getNode(keyNodeOrEntry);
|
|
548
598
|
if (!curr) return deletedResult;
|
|
549
599
|
|
|
550
|
-
const parent:
|
|
551
|
-
let needBalanced:
|
|
552
|
-
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;
|
|
553
603
|
|
|
554
604
|
if (!curr.left && !curr.right && !parent) {
|
|
555
605
|
this._setRoot(undefined);
|
|
@@ -589,41 +639,45 @@ export class BinaryTree<
|
|
|
589
639
|
* Time Complexity: O(n)
|
|
590
640
|
* Space Complexity: O(k + log n)
|
|
591
641
|
*
|
|
592
|
-
* The
|
|
593
|
-
* or
|
|
594
|
-
* @param {BTNRep<K, V,
|
|
595
|
-
*
|
|
596
|
-
* @param [onlyOne=false] - The `onlyOne` parameter in the `
|
|
597
|
-
* determines whether
|
|
598
|
-
*
|
|
599
|
-
* @param {
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
* @
|
|
607
|
-
*
|
|
642
|
+
* The `search` function in TypeScript performs a depth-first or breadth-first search on a tree
|
|
643
|
+
* structure based on a given predicate or key, with options to return multiple results or just one.
|
|
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:
|
|
646
|
+
* @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that
|
|
647
|
+
* determines whether the search should stop after finding the first matching node. If `onlyOne` is
|
|
648
|
+
* set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is
|
|
649
|
+
* @param {C} callback - The `callback` parameter in the `search` function is a callback function
|
|
650
|
+
* that will be called on each node that matches the search criteria. It is of type `C`, which
|
|
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
|
|
653
|
+
* used to specify the node from which the search operation should begin. It represents the starting
|
|
654
|
+
* point in the binary tree where the search will be performed. If no specific `startNode` is
|
|
655
|
+
* provided, the search operation will start from the root
|
|
656
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `search` function
|
|
657
|
+
* specifies the type of iteration to be used when searching for nodes in a binary tree. It can have
|
|
658
|
+
* two possible values:
|
|
659
|
+
* @returns The `search` function returns an array of values that match the provided criteria based
|
|
660
|
+
* on the search algorithm implemented within the function.
|
|
608
661
|
*/
|
|
609
|
-
|
|
610
|
-
|
|
662
|
+
search<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
663
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
|
|
611
664
|
onlyOne = false,
|
|
612
|
-
|
|
665
|
+
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
666
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
613
667
|
iterationType: IterationType = this.iterationType
|
|
614
|
-
):
|
|
615
|
-
if (
|
|
616
|
-
if (
|
|
668
|
+
): ReturnType<C>[] {
|
|
669
|
+
if (keyNodeEntryOrPredicate === undefined) return [];
|
|
670
|
+
if (keyNodeEntryOrPredicate === null) return [];
|
|
617
671
|
startNode = this.ensureNode(startNode);
|
|
618
672
|
if (!startNode) return [];
|
|
619
|
-
const
|
|
673
|
+
const predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
|
|
620
674
|
|
|
621
|
-
const ans:
|
|
675
|
+
const ans: ReturnType<C>[] = [];
|
|
622
676
|
|
|
623
677
|
if (iterationType === 'RECURSIVE') {
|
|
624
|
-
const dfs = (cur:
|
|
625
|
-
if (
|
|
626
|
-
ans.push(cur);
|
|
678
|
+
const dfs = (cur: BinaryTreeNode<K, V>) => {
|
|
679
|
+
if (predicate(cur)) {
|
|
680
|
+
ans.push(callback(cur));
|
|
627
681
|
if (onlyOne) return;
|
|
628
682
|
}
|
|
629
683
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;
|
|
@@ -637,8 +691,8 @@ export class BinaryTree<
|
|
|
637
691
|
while (stack.length > 0) {
|
|
638
692
|
const cur = stack.pop();
|
|
639
693
|
if (this.isRealNode(cur)) {
|
|
640
|
-
if (
|
|
641
|
-
ans.push(cur);
|
|
694
|
+
if (predicate(cur)) {
|
|
695
|
+
ans.push(callback(cur));
|
|
642
696
|
if (onlyOne) return ans;
|
|
643
697
|
}
|
|
644
698
|
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
@@ -652,14 +706,44 @@ export class BinaryTree<
|
|
|
652
706
|
|
|
653
707
|
/**
|
|
654
708
|
* Time Complexity: O(n)
|
|
655
|
-
* Space Complexity: O(log n)
|
|
709
|
+
* Space Complexity: O(k + log n)
|
|
710
|
+
*
|
|
711
|
+
* The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
|
|
712
|
+
* or predicate, with options for recursive or iterative traversal.
|
|
713
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
|
|
714
|
+
* - The `getNodes` function you provided takes several parameters:
|
|
715
|
+
* @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
|
|
716
|
+
* determines whether to return only the first node that matches the criteria specified by the
|
|
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
|
|
719
|
+
* `getNodes` function is used to specify the starting point for traversing the binary tree. It
|
|
720
|
+
* represents the root node of the binary tree or the node from which the traversal should begin. If
|
|
721
|
+
* not provided, the default value is set to `this._root
|
|
722
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` function
|
|
723
|
+
* determines the type of iteration to be performed when traversing the nodes of a binary tree. It
|
|
724
|
+
* can have two possible values:
|
|
725
|
+
* @returns The `getNodes` function returns an array of nodes that satisfy the provided condition
|
|
726
|
+
* based on the input parameters and the iteration type specified.
|
|
727
|
+
*/
|
|
728
|
+
getNodes(
|
|
729
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>,
|
|
730
|
+
onlyOne = false,
|
|
731
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
732
|
+
iterationType: IterationType = this.iterationType
|
|
733
|
+
): BinaryTreeNode<K, V>[] {
|
|
734
|
+
return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Time Complexity: O(n)
|
|
739
|
+
* Space Complexity: O(log n)
|
|
656
740
|
*
|
|
657
741
|
* The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
|
|
658
742
|
* predicate.
|
|
659
|
-
* @param {BTNRep<K, V,
|
|
660
|
-
* - 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,
|
|
661
745
|
* node, entry, raw data, or a predicate function.
|
|
662
|
-
* @param {BTNRep<K, V,
|
|
746
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
663
747
|
* `getNode` function is used to specify the starting point for searching for a node in a binary
|
|
664
748
|
* tree. If no specific starting point is provided, the default value is set to `this._root`, which
|
|
665
749
|
* is typically the root node of the binary tree.
|
|
@@ -671,28 +755,11 @@ export class BinaryTree<
|
|
|
671
755
|
* or `null` if no matching node is found.
|
|
672
756
|
*/
|
|
673
757
|
getNode(
|
|
674
|
-
|
|
675
|
-
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,
|
|
676
760
|
iterationType: IterationType = this.iterationType
|
|
677
|
-
): OptNodeOrNull<
|
|
678
|
-
return this.
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
* Time Complexity: O(n)
|
|
683
|
-
* Space Complexity: O(log n)
|
|
684
|
-
*
|
|
685
|
-
* The function `getNodeByKey` retrieves a node by its key from a binary tree structure.
|
|
686
|
-
* @param {K} key - The `key` parameter is the value used to search for a specific node in a data
|
|
687
|
-
* structure.
|
|
688
|
-
* @param {IterationType} iterationType - The `iterationType` parameter is a type of iteration that
|
|
689
|
-
* specifies how the tree nodes should be traversed when searching for a node with the given key. It
|
|
690
|
-
* is an optional parameter with a default value of `this.iterationType`.
|
|
691
|
-
* @returns The `getNodeByKey` function is returning an optional binary tree node
|
|
692
|
-
* (`OptNodeOrNull<NODE>`).
|
|
693
|
-
*/
|
|
694
|
-
getNodeByKey(key: K, iterationType: IterationType = this.iterationType): OptNodeOrNull<NODE> {
|
|
695
|
-
return this.getNode(key, this._root, iterationType);
|
|
761
|
+
): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
762
|
+
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];
|
|
696
763
|
}
|
|
697
764
|
|
|
698
765
|
/**
|
|
@@ -701,10 +768,10 @@ export class BinaryTree<
|
|
|
701
768
|
*
|
|
702
769
|
* This function overrides the `get` method to retrieve the value associated with a specified key,
|
|
703
770
|
* node, entry, raw data, or predicate in a data structure.
|
|
704
|
-
* @param {BTNRep<K, V,
|
|
705
|
-
* - 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
|
|
706
773
|
* following types:
|
|
707
|
-
* @param {BTNRep<K, V,
|
|
774
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `get`
|
|
708
775
|
* method is used to specify the starting point for searching for a key or node in the binary tree.
|
|
709
776
|
* If no specific starting point is provided, the default starting point is the root of the binary
|
|
710
777
|
* tree (`this._root`).
|
|
@@ -718,16 +785,16 @@ export class BinaryTree<
|
|
|
718
785
|
* `undefined`.
|
|
719
786
|
*/
|
|
720
787
|
override get(
|
|
721
|
-
|
|
722
|
-
startNode: BTNRep<K, V,
|
|
788
|
+
keyNodeEntryOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
789
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
723
790
|
iterationType: IterationType = this.iterationType
|
|
724
791
|
): V | undefined {
|
|
725
792
|
if (this._isMapMode) {
|
|
726
|
-
const key = this.
|
|
793
|
+
const key = this._extractKey(keyNodeEntryOrPredicate);
|
|
727
794
|
if (key === null || key === undefined) return;
|
|
728
795
|
return this._store.get(key);
|
|
729
796
|
}
|
|
730
|
-
return this.getNode(
|
|
797
|
+
return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;
|
|
731
798
|
}
|
|
732
799
|
|
|
733
800
|
/**
|
|
@@ -736,10 +803,10 @@ export class BinaryTree<
|
|
|
736
803
|
*
|
|
737
804
|
* The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
|
|
738
805
|
* exists in the data structure.
|
|
739
|
-
* @param {BTNRep<K, V,
|
|
740
|
-
* - 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
|
|
741
808
|
* the following types:
|
|
742
|
-
* @param {BTNRep<K, V,
|
|
809
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
743
810
|
* `override` method is used to specify the starting point for the search operation within the data
|
|
744
811
|
* structure. It defaults to `this._root` if not provided explicitly.
|
|
745
812
|
* @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
|
|
@@ -752,18 +819,18 @@ export class BinaryTree<
|
|
|
752
819
|
* Otherwise, it returns `false`.
|
|
753
820
|
*/
|
|
754
821
|
override has(
|
|
755
|
-
|
|
756
|
-
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,
|
|
757
824
|
iterationType: IterationType = this.iterationType
|
|
758
825
|
): boolean {
|
|
759
|
-
return this.
|
|
826
|
+
return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;
|
|
760
827
|
}
|
|
761
828
|
|
|
762
829
|
/**
|
|
763
830
|
* Time Complexity: O(1)
|
|
764
831
|
* Space Complexity: O(1)
|
|
765
832
|
*
|
|
766
|
-
* The
|
|
833
|
+
* The clear function removes nodes and values in map mode.
|
|
767
834
|
*/
|
|
768
835
|
clear() {
|
|
769
836
|
this._clearNodes();
|
|
@@ -789,7 +856,7 @@ export class BinaryTree<
|
|
|
789
856
|
*
|
|
790
857
|
* The function checks if a binary tree is perfectly balanced by comparing its minimum height with
|
|
791
858
|
* its height.
|
|
792
|
-
* @param {BTNRep<K, V,
|
|
859
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
793
860
|
* point for checking if the binary tree is perfectly balanced. It represents the root node of the
|
|
794
861
|
* binary tree or a specific node from which the balance check should begin.
|
|
795
862
|
* @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
|
|
@@ -798,17 +865,17 @@ export class BinaryTree<
|
|
|
798
865
|
* height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
|
|
799
866
|
* balanced and
|
|
800
867
|
*/
|
|
801
|
-
isPerfectlyBalanced(startNode: BTNRep<K, V,
|
|
868
|
+
isPerfectlyBalanced(startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root): boolean {
|
|
802
869
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
803
870
|
}
|
|
804
871
|
|
|
805
872
|
/**
|
|
806
873
|
* Time Complexity: O(n)
|
|
807
|
-
* Space Complexity: O(
|
|
874
|
+
* Space Complexity: O(log n)
|
|
808
875
|
*
|
|
809
876
|
* The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
|
|
810
877
|
* or iterative methods.
|
|
811
|
-
* @param {BTNRep<K, V,
|
|
878
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `isBST`
|
|
812
879
|
* function represents the starting point for checking whether a binary search tree (BST) is valid.
|
|
813
880
|
* It can be a node in the BST or a reference to the root of the BST. If no specific node is
|
|
814
881
|
* provided, the function will default to
|
|
@@ -820,13 +887,16 @@ export class BinaryTree<
|
|
|
820
887
|
* the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
|
|
821
888
|
* less than the node's key, and all nodes in its right subtree have keys greater than the node's
|
|
822
889
|
*/
|
|
823
|
-
isBST(
|
|
890
|
+
isBST(
|
|
891
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
892
|
+
iterationType: IterationType = this.iterationType
|
|
893
|
+
): boolean {
|
|
824
894
|
// TODO there is a bug
|
|
825
895
|
startNode = this.ensureNode(startNode);
|
|
826
896
|
if (!startNode) return true;
|
|
827
897
|
|
|
828
898
|
if (iterationType === 'RECURSIVE') {
|
|
829
|
-
const dfs = (cur: OptNodeOrNull<
|
|
899
|
+
const dfs = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>, min: number, max: number): boolean => {
|
|
830
900
|
if (!this.isRealNode(cur)) return true;
|
|
831
901
|
const numKey = Number(cur.key);
|
|
832
902
|
if (numKey <= min || numKey >= max) return false;
|
|
@@ -841,7 +911,7 @@ export class BinaryTree<
|
|
|
841
911
|
const stack = [];
|
|
842
912
|
let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
|
|
843
913
|
// @ts-ignore
|
|
844
|
-
let curr: OptNodeOrNull<
|
|
914
|
+
let curr: OptNodeOrNull<BinaryTreeNode<K, V>> = startNode;
|
|
845
915
|
while (this.isRealNode(curr) || stack.length > 0) {
|
|
846
916
|
while (this.isRealNode(curr)) {
|
|
847
917
|
stack.push(curr);
|
|
@@ -863,13 +933,13 @@ export class BinaryTree<
|
|
|
863
933
|
|
|
864
934
|
/**
|
|
865
935
|
* Time Complexity: O(n)
|
|
866
|
-
* Space Complexity: O(
|
|
936
|
+
* Space Complexity: O(log n)
|
|
867
937
|
*
|
|
868
938
|
* The `getDepth` function calculates the depth between two nodes in a binary tree.
|
|
869
|
-
* @param {BTNRep<K, V,
|
|
939
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} dist - The `dist` parameter in the `getDepth`
|
|
870
940
|
* function represents the node or entry in a binary tree map, or a reference to a node in the tree.
|
|
871
941
|
* It is the target node for which you want to calculate the depth from the `startNode` node.
|
|
872
|
-
* @param {BTNRep<K, V,
|
|
942
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
873
943
|
* `getDepth` function represents the starting point from which you want to calculate the depth of a
|
|
874
944
|
* given node or entry in a binary tree. If no specific starting point is provided, the default value
|
|
875
945
|
* for `startNode` is set to the root of the binary
|
|
@@ -877,7 +947,10 @@ export class BinaryTree<
|
|
|
877
947
|
* `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
|
|
878
948
|
* node, it returns the depth of the `dist` node from the root of the tree.
|
|
879
949
|
*/
|
|
880
|
-
getDepth(
|
|
950
|
+
getDepth(
|
|
951
|
+
dist: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
952
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root
|
|
953
|
+
): number {
|
|
881
954
|
let distEnsured = this.ensureNode(dist);
|
|
882
955
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
883
956
|
let depth = 0;
|
|
@@ -893,11 +966,11 @@ export class BinaryTree<
|
|
|
893
966
|
|
|
894
967
|
/**
|
|
895
968
|
* Time Complexity: O(n)
|
|
896
|
-
* Space Complexity: O(
|
|
969
|
+
* Space Complexity: O(log n)
|
|
897
970
|
*
|
|
898
971
|
* The `getHeight` function calculates the maximum height of a binary tree using either a recursive
|
|
899
972
|
* or iterative approach in TypeScript.
|
|
900
|
-
* @param {BTNRep<K, V,
|
|
973
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter is the starting
|
|
901
974
|
* point from which the height of the binary tree will be calculated. It can be a node in the binary
|
|
902
975
|
* tree or a reference to the root of the tree. If not provided, it defaults to the root of the
|
|
903
976
|
* binary tree data structure.
|
|
@@ -908,12 +981,15 @@ export class BinaryTree<
|
|
|
908
981
|
* root node. The height is calculated based on the maximum depth of the tree, considering either a
|
|
909
982
|
* recursive approach or an iterative approach depending on the `iterationType` parameter.
|
|
910
983
|
*/
|
|
911
|
-
getHeight(
|
|
984
|
+
getHeight(
|
|
985
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
986
|
+
iterationType: IterationType = this.iterationType
|
|
987
|
+
): number {
|
|
912
988
|
startNode = this.ensureNode(startNode);
|
|
913
989
|
if (!this.isRealNode(startNode)) return -1;
|
|
914
990
|
|
|
915
991
|
if (iterationType === 'RECURSIVE') {
|
|
916
|
-
const _getMaxHeight = (cur: OptNodeOrNull<
|
|
992
|
+
const _getMaxHeight = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>): number => {
|
|
917
993
|
if (!this.isRealNode(cur)) return -1;
|
|
918
994
|
const leftHeight = _getMaxHeight(cur.left);
|
|
919
995
|
const rightHeight = _getMaxHeight(cur.right);
|
|
@@ -922,7 +998,7 @@ export class BinaryTree<
|
|
|
922
998
|
|
|
923
999
|
return _getMaxHeight(startNode);
|
|
924
1000
|
} else {
|
|
925
|
-
const stack: { node:
|
|
1001
|
+
const stack: { node: BinaryTreeNode<K, V>; depth: number }[] = [{ node: startNode, depth: 0 }];
|
|
926
1002
|
let maxHeight = 0;
|
|
927
1003
|
|
|
928
1004
|
while (stack.length > 0) {
|
|
@@ -944,7 +1020,7 @@ export class BinaryTree<
|
|
|
944
1020
|
*
|
|
945
1021
|
* The `getMinHeight` function calculates the minimum height of a binary tree using either a
|
|
946
1022
|
* recursive or iterative approach in TypeScript.
|
|
947
|
-
* @param {BTNRep<K, V,
|
|
1023
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
948
1024
|
* `getMinHeight` function represents the starting node from which the minimum height of the binary
|
|
949
1025
|
* tree will be calculated. It is either a node in the binary tree or a reference to the root of the
|
|
950
1026
|
* tree. If not provided, the default value is the root
|
|
@@ -957,14 +1033,14 @@ export class BinaryTree<
|
|
|
957
1033
|
* a stack) based on the `iterationType` parameter.
|
|
958
1034
|
*/
|
|
959
1035
|
getMinHeight(
|
|
960
|
-
startNode: BTNRep<K, V,
|
|
1036
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
961
1037
|
iterationType: IterationType = this.iterationType
|
|
962
1038
|
): number {
|
|
963
1039
|
startNode = this.ensureNode(startNode);
|
|
964
1040
|
if (!startNode) return -1;
|
|
965
1041
|
|
|
966
1042
|
if (iterationType === 'RECURSIVE') {
|
|
967
|
-
const _getMinHeight = (cur: OptNodeOrNull<
|
|
1043
|
+
const _getMinHeight = (cur: OptNodeOrNull<BinaryTreeNode<K, V>>): number => {
|
|
968
1044
|
if (!this.isRealNode(cur)) return 0;
|
|
969
1045
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;
|
|
970
1046
|
const leftMinHeight = _getMinHeight(cur.left);
|
|
@@ -974,10 +1050,10 @@ export class BinaryTree<
|
|
|
974
1050
|
|
|
975
1051
|
return _getMinHeight(startNode);
|
|
976
1052
|
} else {
|
|
977
|
-
const stack:
|
|
978
|
-
let node: OptNodeOrNull<
|
|
979
|
-
last: OptNodeOrNull<
|
|
980
|
-
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();
|
|
981
1057
|
|
|
982
1058
|
while (stack.length > 0 || node) {
|
|
983
1059
|
if (this.isRealNode(node)) {
|
|
@@ -1012,7 +1088,7 @@ export class BinaryTree<
|
|
|
1012
1088
|
* the path to the root. It is expected to be a function that takes a node as an argument and returns
|
|
1013
1089
|
* a value based on that node. The return type of the callback function is determined by the generic
|
|
1014
1090
|
* type `C
|
|
1015
|
-
* @param {BTNRep<K, V,
|
|
1091
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} beginNode - The `beginNode` parameter in the
|
|
1016
1092
|
* `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
|
|
1017
1093
|
* @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
|
|
1018
1094
|
* whether the resulting path from the given `beginNode` to the root should be in reverse order or
|
|
@@ -1022,10 +1098,10 @@ export class BinaryTree<
|
|
|
1022
1098
|
* array is either in reverse order or in the original order based on the value of the `isReverse`
|
|
1023
1099
|
* parameter.
|
|
1024
1100
|
*/
|
|
1025
|
-
getPathToRoot<C extends NodeCallback<OptNodeOrNull<
|
|
1101
|
+
getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1102
|
+
beginNode: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1026
1103
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1027
|
-
|
|
1028
|
-
isReverse = true
|
|
1104
|
+
isReverse = false
|
|
1029
1105
|
): ReturnType<C>[] {
|
|
1030
1106
|
const result: ReturnType<C>[] = [];
|
|
1031
1107
|
let beginNodeEnsured = this.ensureNode(beginNode);
|
|
@@ -1043,14 +1119,14 @@ export class BinaryTree<
|
|
|
1043
1119
|
|
|
1044
1120
|
/**
|
|
1045
1121
|
* Time Complexity: O(log n)
|
|
1046
|
-
* Space Complexity: O(
|
|
1122
|
+
* Space Complexity: O(log n)
|
|
1047
1123
|
*
|
|
1048
1124
|
* The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or
|
|
1049
1125
|
* tail-recursive iteration.
|
|
1050
1126
|
* @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
|
|
1051
1127
|
* node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
|
|
1052
1128
|
* value of `_DEFAULT_NODE_CALLBACK` if not specified.
|
|
1053
|
-
* @param {BTNRep<K, V,
|
|
1129
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1054
1130
|
* `getLeftMost` function represents the starting point for finding the leftmost node in a binary
|
|
1055
1131
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1056
1132
|
* starting point is provided, the function will default
|
|
@@ -1062,9 +1138,9 @@ export class BinaryTree<
|
|
|
1062
1138
|
* `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`
|
|
1063
1139
|
* node is not a real node, it returns the result of the callback
|
|
1064
1140
|
*/
|
|
1065
|
-
getLeftMost<C extends NodeCallback<OptNodeOrNull<
|
|
1141
|
+
getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1066
1142
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1067
|
-
startNode: BTNRep<K, V,
|
|
1143
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1068
1144
|
iterationType: IterationType = this.iterationType
|
|
1069
1145
|
): ReturnType<C> {
|
|
1070
1146
|
if (this.isNIL(startNode)) return callback(undefined);
|
|
@@ -1073,7 +1149,7 @@ export class BinaryTree<
|
|
|
1073
1149
|
if (!this.isRealNode(startNode)) return callback(startNode);
|
|
1074
1150
|
|
|
1075
1151
|
if (iterationType === 'RECURSIVE') {
|
|
1076
|
-
const dfs = (cur:
|
|
1152
|
+
const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
|
|
1077
1153
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1078
1154
|
return dfs(cur.left);
|
|
1079
1155
|
};
|
|
@@ -1081,7 +1157,7 @@ export class BinaryTree<
|
|
|
1081
1157
|
return callback(dfs(startNode));
|
|
1082
1158
|
} else {
|
|
1083
1159
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1084
|
-
const dfs = trampoline((cur:
|
|
1160
|
+
const dfs = trampoline((cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
|
|
1085
1161
|
if (!this.isRealNode(cur.left)) return cur;
|
|
1086
1162
|
return dfs.cont(cur.left);
|
|
1087
1163
|
});
|
|
@@ -1092,15 +1168,15 @@ export class BinaryTree<
|
|
|
1092
1168
|
|
|
1093
1169
|
/**
|
|
1094
1170
|
* Time Complexity: O(log n)
|
|
1095
|
-
* Space Complexity: O(
|
|
1171
|
+
* Space Complexity: O(log n)
|
|
1096
1172
|
*
|
|
1097
1173
|
* The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
|
|
1098
1174
|
* or iterative traversal methods.
|
|
1099
1175
|
* @param {C} callback - The `callback` parameter is a function that will be called with the result
|
|
1100
|
-
* 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>>>`,
|
|
1101
1177
|
* which means it is a callback function that can accept either an optional binary tree node or null
|
|
1102
1178
|
* as
|
|
1103
|
-
* @param {BTNRep<K, V,
|
|
1179
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1104
1180
|
* `getRightMost` function represents the starting point for finding the rightmost node in a binary
|
|
1105
1181
|
* tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
|
|
1106
1182
|
* starting point is provided, the function will default
|
|
@@ -1112,18 +1188,17 @@ export class BinaryTree<
|
|
|
1112
1188
|
* the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
|
|
1113
1189
|
* other).
|
|
1114
1190
|
*/
|
|
1115
|
-
getRightMost<C extends NodeCallback<OptNodeOrNull<
|
|
1191
|
+
getRightMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1116
1192
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1117
|
-
startNode: BTNRep<K, V,
|
|
1193
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1118
1194
|
iterationType: IterationType = this.iterationType
|
|
1119
1195
|
): ReturnType<C> {
|
|
1120
1196
|
if (this.isNIL(startNode)) return callback(undefined);
|
|
1121
|
-
// TODO support get right most by passing key in
|
|
1122
1197
|
startNode = this.ensureNode(startNode);
|
|
1123
1198
|
if (!startNode) return callback(startNode);
|
|
1124
1199
|
|
|
1125
1200
|
if (iterationType === 'RECURSIVE') {
|
|
1126
|
-
const dfs = (cur:
|
|
1201
|
+
const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {
|
|
1127
1202
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1128
1203
|
return dfs(cur.right);
|
|
1129
1204
|
};
|
|
@@ -1131,7 +1206,7 @@ export class BinaryTree<
|
|
|
1131
1206
|
return callback(dfs(startNode));
|
|
1132
1207
|
} else {
|
|
1133
1208
|
// Indirect implementation of iteration using tail recursion optimization
|
|
1134
|
-
const dfs = trampoline((cur:
|
|
1209
|
+
const dfs = trampoline((cur: BinaryTreeNode<K, V>) => {
|
|
1135
1210
|
if (!this.isRealNode(cur.right)) return cur;
|
|
1136
1211
|
return dfs.cont(cur.right);
|
|
1137
1212
|
});
|
|
@@ -1142,20 +1217,20 @@ export class BinaryTree<
|
|
|
1142
1217
|
|
|
1143
1218
|
/**
|
|
1144
1219
|
* Time Complexity: O(log n)
|
|
1145
|
-
* Space Complexity: O(
|
|
1220
|
+
* Space Complexity: O(log n)
|
|
1146
1221
|
*
|
|
1147
1222
|
* The function `getPredecessor` in TypeScript returns the predecessor node of a given node in a
|
|
1148
1223
|
* binary tree.
|
|
1149
|
-
* @param {
|
|
1224
|
+
* @param {BinaryTreeNode<K, V>} node - The `getPredecessor` function you provided seems to be attempting to find the
|
|
1150
1225
|
* predecessor of a given node in a binary tree. However, there seems to be a logical issue in the
|
|
1151
1226
|
* while loop condition that might cause an infinite loop.
|
|
1152
|
-
* @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.
|
|
1153
1228
|
* If the left child of the input node exists, it traverses to the rightmost node of the left subtree
|
|
1154
1229
|
* to find the predecessor. If the left child does not exist, it returns the input node itself.
|
|
1155
1230
|
*/
|
|
1156
|
-
getPredecessor(node:
|
|
1231
|
+
getPredecessor(node: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
|
|
1157
1232
|
if (this.isRealNode(node.left)) {
|
|
1158
|
-
let predecessor: OptNodeOrNull<
|
|
1233
|
+
let predecessor: OptNodeOrNull<BinaryTreeNode<K, V>> = node.left;
|
|
1159
1234
|
while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {
|
|
1160
1235
|
if (this.isRealNode(predecessor)) {
|
|
1161
1236
|
predecessor = predecessor.right;
|
|
@@ -1169,18 +1244,18 @@ export class BinaryTree<
|
|
|
1169
1244
|
|
|
1170
1245
|
/**
|
|
1171
1246
|
* Time Complexity: O(log n)
|
|
1172
|
-
* Space Complexity: O(
|
|
1247
|
+
* Space Complexity: O(log n)
|
|
1173
1248
|
*
|
|
1174
1249
|
* The function `getSuccessor` in TypeScript returns the next node in an in-order traversal of a
|
|
1175
1250
|
* binary tree.
|
|
1176
|
-
* @param {K |
|
|
1177
|
-
* 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`.
|
|
1178
1253
|
* @returns The `getSuccessor` function returns the successor node of the input node `x`. If `x` has
|
|
1179
1254
|
* a right child, the function returns the leftmost node in the right subtree of `x`. If `x` does not
|
|
1180
1255
|
* have a right child, the function traverses up the parent nodes until it finds a node that is not
|
|
1181
1256
|
* the right child of its parent, and returns that node
|
|
1182
1257
|
*/
|
|
1183
|
-
getSuccessor(x?: K |
|
|
1258
|
+
getSuccessor(x?: K | BinaryTreeNode<K, V> | null): OptNodeOrNull<BinaryTreeNode<K, V>> {
|
|
1184
1259
|
x = this.ensureNode(x);
|
|
1185
1260
|
if (!this.isRealNode(x)) return undefined;
|
|
1186
1261
|
|
|
@@ -1188,7 +1263,7 @@ export class BinaryTree<
|
|
|
1188
1263
|
return this.getLeftMost(node => node, x.right);
|
|
1189
1264
|
}
|
|
1190
1265
|
|
|
1191
|
-
let y: OptNodeOrNull<
|
|
1266
|
+
let y: OptNodeOrNull<BinaryTreeNode<K, V>> = x.parent;
|
|
1192
1267
|
while (this.isRealNode(y) && x === y.right) {
|
|
1193
1268
|
x = y;
|
|
1194
1269
|
y = y.parent;
|
|
@@ -1196,17 +1271,17 @@ export class BinaryTree<
|
|
|
1196
1271
|
return y;
|
|
1197
1272
|
}
|
|
1198
1273
|
|
|
1199
|
-
dfs<C extends NodeCallback<
|
|
1274
|
+
dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1200
1275
|
callback?: C,
|
|
1201
1276
|
pattern?: DFSOrderPattern,
|
|
1202
|
-
startNode?: BTNRep<K, V,
|
|
1277
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1203
1278
|
iterationType?: IterationType
|
|
1204
1279
|
): ReturnType<C>[];
|
|
1205
1280
|
|
|
1206
|
-
dfs<C extends NodeCallback<
|
|
1281
|
+
dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1207
1282
|
callback?: C,
|
|
1208
1283
|
pattern?: DFSOrderPattern,
|
|
1209
|
-
startNode?: BTNRep<K, V,
|
|
1284
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1210
1285
|
iterationType?: IterationType,
|
|
1211
1286
|
includeNull?: boolean
|
|
1212
1287
|
): ReturnType<C>[];
|
|
@@ -1218,12 +1293,12 @@ export class BinaryTree<
|
|
|
1218
1293
|
* The function `dfs` performs a depth-first search traversal on a binary tree structure based on the
|
|
1219
1294
|
* specified parameters.
|
|
1220
1295
|
* @param {C} callback - The `callback` parameter is a generic type `C` that extends the
|
|
1221
|
-
* `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
|
|
1222
1297
|
* `this._DEFAULT_NODE_CALLBACK as C`.
|
|
1223
1298
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` method specifies the
|
|
1224
1299
|
* order in which the Depth-First Search (DFS) algorithm should traverse the nodes in the tree. The
|
|
1225
1300
|
* possible values for the `pattern` parameter are:
|
|
1226
|
-
* @param {BTNRep<K, V,
|
|
1301
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `dfs`
|
|
1227
1302
|
* method is used to specify the starting point for the Depth-First Search traversal. It can be
|
|
1228
1303
|
* either a `BTNRep` object representing a key, node, or entry in the binary tree map,
|
|
1229
1304
|
* or it can be a
|
|
@@ -1237,10 +1312,10 @@ export class BinaryTree<
|
|
|
1237
1312
|
* @returns The `dfs` method is returning an array of the return type specified by the generic type
|
|
1238
1313
|
* parameter `C`. The return type is determined by the callback function provided to the method.
|
|
1239
1314
|
*/
|
|
1240
|
-
dfs<C extends NodeCallback<OptNodeOrNull<
|
|
1315
|
+
dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1241
1316
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1242
1317
|
pattern: DFSOrderPattern = 'IN',
|
|
1243
|
-
startNode: BTNRep<K, V,
|
|
1318
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1244
1319
|
iterationType: IterationType = this.iterationType,
|
|
1245
1320
|
includeNull = false
|
|
1246
1321
|
): ReturnType<C>[] {
|
|
@@ -1249,16 +1324,16 @@ export class BinaryTree<
|
|
|
1249
1324
|
return this._dfs(callback, pattern, startNode, iterationType, includeNull);
|
|
1250
1325
|
}
|
|
1251
1326
|
|
|
1252
|
-
bfs<C extends NodeCallback<
|
|
1327
|
+
bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1253
1328
|
callback?: C,
|
|
1254
|
-
startNode?: BTNRep<K, V,
|
|
1329
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1255
1330
|
iterationType?: IterationType,
|
|
1256
1331
|
includeNull?: false
|
|
1257
1332
|
): ReturnType<C>[];
|
|
1258
1333
|
|
|
1259
|
-
bfs<C extends NodeCallback<
|
|
1334
|
+
bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1260
1335
|
callback?: C,
|
|
1261
|
-
startNode?: BTNRep<K, V,
|
|
1336
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1262
1337
|
iterationType?: IterationType,
|
|
1263
1338
|
includeNull?: true
|
|
1264
1339
|
): ReturnType<C>[];
|
|
@@ -1271,8 +1346,8 @@ export class BinaryTree<
|
|
|
1271
1346
|
* tree, executing a specified callback function on each node visited.
|
|
1272
1347
|
* @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
|
|
1273
1348
|
* called on each node visited during the breadth-first search traversal. It is a generic type `C`
|
|
1274
|
-
* that extends the `NodeCallback` type, which takes a parameter of type `
|
|
1275
|
-
* @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`
|
|
1276
1351
|
* function represents the starting point for the breadth-first search traversal in a binary tree. It
|
|
1277
1352
|
* can be specified as a key, node, or entry in the binary tree structure. If not provided, the
|
|
1278
1353
|
* default value is the root node of the binary
|
|
@@ -1286,19 +1361,21 @@ export class BinaryTree<
|
|
|
1286
1361
|
* @returns The `bfs` function returns an array of values that are the result of applying the
|
|
1287
1362
|
* provided callback function to each node in the binary tree in a breadth-first search manner.
|
|
1288
1363
|
*/
|
|
1289
|
-
bfs<C extends NodeCallback<
|
|
1364
|
+
bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1290
1365
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1291
|
-
startNode: BTNRep<K, V,
|
|
1366
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1292
1367
|
iterationType: IterationType = this.iterationType,
|
|
1293
1368
|
includeNull = false
|
|
1294
1369
|
): ReturnType<C>[] {
|
|
1295
1370
|
startNode = this.ensureNode(startNode);
|
|
1296
1371
|
if (!startNode) return [];
|
|
1297
1372
|
|
|
1298
|
-
const ans: ReturnType<NodeCallback<
|
|
1373
|
+
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
|
|
1299
1374
|
|
|
1300
1375
|
if (iterationType === 'RECURSIVE') {
|
|
1301
|
-
const queue: Queue<OptNodeOrNull<
|
|
1376
|
+
const queue: Queue<OptNodeOrNull<BinaryTreeNode<K, V>>> = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([
|
|
1377
|
+
startNode
|
|
1378
|
+
]);
|
|
1302
1379
|
|
|
1303
1380
|
const dfs = (level: number) => {
|
|
1304
1381
|
if (queue.size === 0) return;
|
|
@@ -1319,7 +1396,7 @@ export class BinaryTree<
|
|
|
1319
1396
|
|
|
1320
1397
|
dfs(0);
|
|
1321
1398
|
} else {
|
|
1322
|
-
const queue = new Queue<OptNodeOrNull<
|
|
1399
|
+
const queue = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([startNode]);
|
|
1323
1400
|
while (queue.size > 0) {
|
|
1324
1401
|
const levelSize = queue.size;
|
|
1325
1402
|
|
|
@@ -1348,7 +1425,7 @@ export class BinaryTree<
|
|
|
1348
1425
|
* structure based on a specified callback and iteration type.
|
|
1349
1426
|
* @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
|
|
1350
1427
|
* in the binary tree. It is optional and defaults to a default callback function if not provided.
|
|
1351
|
-
* @param {BTNRep<K, V,
|
|
1428
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `leaves`
|
|
1352
1429
|
* method is used to specify the starting point for finding and processing the leaves of a binary
|
|
1353
1430
|
* tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
|
|
1354
1431
|
* explicitly provided, the default value
|
|
@@ -1358,17 +1435,17 @@ export class BinaryTree<
|
|
|
1358
1435
|
* @returns The `leaves` method returns an array of values that are the result of applying the
|
|
1359
1436
|
* provided callback function to each leaf node in the binary tree.
|
|
1360
1437
|
*/
|
|
1361
|
-
leaves<C extends NodeCallback<
|
|
1438
|
+
leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1362
1439
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1363
|
-
startNode: BTNRep<K, V,
|
|
1440
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1364
1441
|
iterationType: IterationType = this.iterationType
|
|
1365
1442
|
): ReturnType<C>[] {
|
|
1366
1443
|
startNode = this.ensureNode(startNode);
|
|
1367
|
-
const leaves: ReturnType<NodeCallback<
|
|
1444
|
+
const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
|
|
1368
1445
|
if (!this.isRealNode(startNode)) return [];
|
|
1369
1446
|
|
|
1370
1447
|
if (iterationType === 'RECURSIVE') {
|
|
1371
|
-
const dfs = (cur:
|
|
1448
|
+
const dfs = (cur: BinaryTreeNode<K, V>) => {
|
|
1372
1449
|
if (this.isLeaf(cur)) {
|
|
1373
1450
|
leaves.push(callback(cur));
|
|
1374
1451
|
}
|
|
@@ -1395,16 +1472,16 @@ export class BinaryTree<
|
|
|
1395
1472
|
return leaves;
|
|
1396
1473
|
}
|
|
1397
1474
|
|
|
1398
|
-
listLevels<C extends NodeCallback<
|
|
1475
|
+
listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1399
1476
|
callback?: C,
|
|
1400
|
-
startNode?: BTNRep<K, V,
|
|
1477
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1401
1478
|
iterationType?: IterationType,
|
|
1402
1479
|
includeNull?: false
|
|
1403
1480
|
): ReturnType<C>[][];
|
|
1404
1481
|
|
|
1405
|
-
listLevels<C extends NodeCallback<
|
|
1482
|
+
listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1406
1483
|
callback?: C,
|
|
1407
|
-
startNode?: BTNRep<K, V,
|
|
1484
|
+
startNode?: BTNRep<K, V, BinaryTreeNode<K, V>>,
|
|
1408
1485
|
iterationType?: IterationType,
|
|
1409
1486
|
includeNull?: true
|
|
1410
1487
|
): ReturnType<C>[][];
|
|
@@ -1418,7 +1495,7 @@ export class BinaryTree<
|
|
|
1418
1495
|
* @param {C} callback - The `callback` parameter is a function that will be applied to each node in
|
|
1419
1496
|
* the binary tree during the traversal. It is used to process each node and determine what
|
|
1420
1497
|
* information to include in the output for each level of the tree.
|
|
1421
|
-
* @param {BTNRep<K, V,
|
|
1498
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1422
1499
|
* `listLevels` function represents the starting point for traversing the binary tree. It can be
|
|
1423
1500
|
* either a key, a node, or an entry in the binary tree. If not provided, the default value is the
|
|
1424
1501
|
* root of the binary tree.
|
|
@@ -1433,9 +1510,9 @@ export class BinaryTree<
|
|
|
1433
1510
|
* level in a binary tree. Each inner array contains the return value of the provided callback
|
|
1434
1511
|
* function applied to the nodes at that level.
|
|
1435
1512
|
*/
|
|
1436
|
-
listLevels<C extends NodeCallback<
|
|
1513
|
+
listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
|
|
1437
1514
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1438
|
-
startNode: BTNRep<K, V,
|
|
1515
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1439
1516
|
iterationType: IterationType = this.iterationType,
|
|
1440
1517
|
includeNull = false
|
|
1441
1518
|
): ReturnType<C>[][] {
|
|
@@ -1444,7 +1521,7 @@ export class BinaryTree<
|
|
|
1444
1521
|
if (!startNode) return levelsNodes;
|
|
1445
1522
|
|
|
1446
1523
|
if (iterationType === 'RECURSIVE') {
|
|
1447
|
-
const _recursive = (node:
|
|
1524
|
+
const _recursive = (node: BinaryTreeNode<K, V> | null, level: number) => {
|
|
1448
1525
|
if (!levelsNodes[level]) levelsNodes[level] = [];
|
|
1449
1526
|
levelsNodes[level].push(callback(node));
|
|
1450
1527
|
if (includeNull) {
|
|
@@ -1458,7 +1535,7 @@ export class BinaryTree<
|
|
|
1458
1535
|
|
|
1459
1536
|
_recursive(startNode, 0);
|
|
1460
1537
|
} else {
|
|
1461
|
-
const stack: [
|
|
1538
|
+
const stack: [BinaryTreeNode<K, V> | null, number][] = [[startNode, 0]];
|
|
1462
1539
|
|
|
1463
1540
|
while (stack.length > 0) {
|
|
1464
1541
|
const head = stack.pop()!;
|
|
@@ -1488,11 +1565,11 @@ export class BinaryTree<
|
|
|
1488
1565
|
* Morris Traversal algorithm with different order patterns.
|
|
1489
1566
|
* @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
|
|
1490
1567
|
* called on each node in the binary tree during the traversal. It is of type `C`, which extends the
|
|
1491
|
-
* `NodeCallback<
|
|
1568
|
+
* `NodeCallback<BinaryTreeNode<K, V>>` type. The default value for `callback` is `this._DEFAULT
|
|
1492
1569
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
|
|
1493
1570
|
* the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
|
|
1494
1571
|
* values for the `pattern` parameter are:
|
|
1495
|
-
* @param {BTNRep<K, V,
|
|
1572
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `morris`
|
|
1496
1573
|
* function is the starting point for the Morris traversal algorithm. It represents the root node of
|
|
1497
1574
|
* the binary tree or the node from which the traversal should begin. It can be provided as either a
|
|
1498
1575
|
* key, a node, an entry, or a reference
|
|
@@ -1500,19 +1577,19 @@ export class BinaryTree<
|
|
|
1500
1577
|
* provided callback function to each node in the binary tree in the specified order pattern (IN,
|
|
1501
1578
|
* PRE, or POST).
|
|
1502
1579
|
*/
|
|
1503
|
-
morris<C extends NodeCallback<
|
|
1580
|
+
morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(
|
|
1504
1581
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1505
1582
|
pattern: DFSOrderPattern = 'IN',
|
|
1506
|
-
startNode: BTNRep<K, V,
|
|
1583
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root
|
|
1507
1584
|
): ReturnType<C>[] {
|
|
1508
1585
|
startNode = this.ensureNode(startNode);
|
|
1509
1586
|
if (!startNode) return [];
|
|
1510
|
-
const ans: ReturnType<NodeCallback<
|
|
1587
|
+
const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V>>>[] = [];
|
|
1511
1588
|
|
|
1512
|
-
let cur: OptNodeOrNull<
|
|
1513
|
-
const _reverseEdge = (node: OptNodeOrNull<
|
|
1514
|
-
let pre: OptNodeOrNull<
|
|
1515
|
-
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;
|
|
1516
1593
|
while (node) {
|
|
1517
1594
|
next = node.right;
|
|
1518
1595
|
node.right = pre;
|
|
@@ -1521,9 +1598,9 @@ export class BinaryTree<
|
|
|
1521
1598
|
}
|
|
1522
1599
|
return pre;
|
|
1523
1600
|
};
|
|
1524
|
-
const _printEdge = (node: OptNodeOrNull<
|
|
1525
|
-
const tail: OptNodeOrNull<
|
|
1526
|
-
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;
|
|
1527
1604
|
while (cur) {
|
|
1528
1605
|
ans.push(callback(cur));
|
|
1529
1606
|
cur = cur.right;
|
|
@@ -1597,8 +1674,13 @@ export class BinaryTree<
|
|
|
1597
1674
|
* original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in
|
|
1598
1675
|
* the original tree is null, a null node is added to the cloned tree. If a node
|
|
1599
1676
|
*/
|
|
1600
|
-
clone()
|
|
1677
|
+
clone() {
|
|
1601
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>) {
|
|
1602
1684
|
this.bfs(
|
|
1603
1685
|
node => {
|
|
1604
1686
|
if (node === null) cloned.add(null);
|
|
@@ -1612,7 +1694,6 @@ export class BinaryTree<
|
|
|
1612
1694
|
true
|
|
1613
1695
|
);
|
|
1614
1696
|
if (this._isMapMode) cloned._store = this._store;
|
|
1615
|
-
return cloned;
|
|
1616
1697
|
}
|
|
1617
1698
|
|
|
1618
1699
|
/**
|
|
@@ -1635,7 +1716,7 @@ export class BinaryTree<
|
|
|
1635
1716
|
const newTree = this.createTree();
|
|
1636
1717
|
let index = 0;
|
|
1637
1718
|
for (const [key, value] of this) {
|
|
1638
|
-
if (predicate.call(thisArg,
|
|
1719
|
+
if (predicate.call(thisArg, key, value, index++, this)) {
|
|
1639
1720
|
newTree.add([key, value]);
|
|
1640
1721
|
}
|
|
1641
1722
|
}
|
|
@@ -1646,43 +1727,41 @@ export class BinaryTree<
|
|
|
1646
1727
|
* Time Complexity: O(n)
|
|
1647
1728
|
* Space Complexity: O(n)
|
|
1648
1729
|
*
|
|
1649
|
-
* The `map` function
|
|
1650
|
-
*
|
|
1651
|
-
* @param callback -
|
|
1652
|
-
*
|
|
1653
|
-
*
|
|
1654
|
-
*
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1657
|
-
*
|
|
1658
|
-
*
|
|
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.
|
|
1659
1744
|
*/
|
|
1660
|
-
map(
|
|
1661
|
-
|
|
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);
|
|
1662
1751
|
let index = 0;
|
|
1663
1752
|
for (const [key, value] of this) {
|
|
1664
|
-
newTree.add(
|
|
1753
|
+
newTree.add(callback.call(thisArg, key, value, index++, this));
|
|
1665
1754
|
}
|
|
1666
1755
|
return newTree;
|
|
1667
1756
|
}
|
|
1668
1757
|
|
|
1669
|
-
// // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
|
1670
|
-
// // map<NV>(callback: (entry: [K, V | undefined], tree: this) => NV) {
|
|
1671
|
-
// // const newTree = this.createTree();
|
|
1672
|
-
// // for (const [key, value] of this) {
|
|
1673
|
-
// // newTree.add(key, callback([key, value], this));
|
|
1674
|
-
// // }
|
|
1675
|
-
// // return newTree;
|
|
1676
|
-
// // }
|
|
1677
|
-
//
|
|
1678
|
-
|
|
1679
1758
|
/**
|
|
1680
1759
|
* Time Complexity: O(n)
|
|
1681
1760
|
* Space Complexity: O(n)
|
|
1682
1761
|
*
|
|
1683
1762
|
* The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
|
|
1684
1763
|
* customizable options for displaying undefined, null, and sentinel nodes.
|
|
1685
|
-
* @param {BTNRep<K, V,
|
|
1764
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1686
1765
|
* `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
|
|
1687
1766
|
* It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
|
|
1688
1767
|
* the default is set to the root
|
|
@@ -1694,7 +1773,10 @@ export class BinaryTree<
|
|
|
1694
1773
|
* the lines to the output string. The final output string contains the visual representation of the
|
|
1695
1774
|
* binary tree with the specified options.
|
|
1696
1775
|
*/
|
|
1697
|
-
override toVisual(
|
|
1776
|
+
override toVisual(
|
|
1777
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1778
|
+
options?: BinaryTreePrintOptions
|
|
1779
|
+
): string {
|
|
1698
1780
|
const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
|
|
1699
1781
|
startNode = this.ensureNode(startNode);
|
|
1700
1782
|
let output = '';
|
|
@@ -1704,8 +1786,8 @@ export class BinaryTree<
|
|
|
1704
1786
|
if (opts.isShowNull) output += `N for null\n`;
|
|
1705
1787
|
if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`;
|
|
1706
1788
|
|
|
1707
|
-
const display = (root: OptNodeOrNull<
|
|
1708
|
-
const [lines
|
|
1789
|
+
const display = (root: OptNodeOrNull<BinaryTreeNode<K, V>>): void => {
|
|
1790
|
+
const [lines] = this._displayAux(root, opts);
|
|
1709
1791
|
let paragraph = '';
|
|
1710
1792
|
for (const line of lines) {
|
|
1711
1793
|
paragraph += line + '\n';
|
|
@@ -1727,15 +1809,53 @@ export class BinaryTree<
|
|
|
1727
1809
|
* printing options for the binary tree. It is an optional parameter that allows you to customize how
|
|
1728
1810
|
* the binary tree is printed, such as choosing between different traversal orders or formatting
|
|
1729
1811
|
* options.
|
|
1730
|
-
* @param {BTNRep<K, V,
|
|
1812
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the
|
|
1731
1813
|
* `override print` method is used to specify the starting point for printing the binary tree. It can
|
|
1732
1814
|
* be either a key, a node, an entry, or the root of the tree. If no specific starting point is
|
|
1733
1815
|
* provided, the default value is set to
|
|
1734
1816
|
*/
|
|
1735
|
-
override print(options?: BinaryTreePrintOptions, startNode: BTNRep<K, V,
|
|
1817
|
+
override print(options?: BinaryTreePrintOptions, startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root) {
|
|
1736
1818
|
console.log(this.toVisual(startNode, options));
|
|
1737
1819
|
}
|
|
1738
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
|
+
|
|
1739
1859
|
/**
|
|
1740
1860
|
* Time complexity: O(n)
|
|
1741
1861
|
* Space complexity: O(n)
|
|
@@ -1744,11 +1864,11 @@ export class BinaryTree<
|
|
|
1744
1864
|
* the specified order pattern and callback function.
|
|
1745
1865
|
* @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
|
|
1746
1866
|
* called on each node visited during the depth-first search traversal. It is of type `C`, which
|
|
1747
|
-
* extends `NodeCallback<OptNodeOrNull<
|
|
1867
|
+
* extends `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`. The default value for this parameter is `this._DEFAULT
|
|
1748
1868
|
* @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
|
|
1749
1869
|
* order in which the nodes are visited during the Depth-First Search traversal. It can have one of
|
|
1750
1870
|
* the following values:
|
|
1751
|
-
* @param {BTNRep<K, V,
|
|
1871
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} startNode - The `startNode` parameter in the `_dfs`
|
|
1752
1872
|
* method is used to specify the starting point for the depth-first search traversal in a binary
|
|
1753
1873
|
* tree. It can be provided as either a `BTNRep` object or a reference to the root node
|
|
1754
1874
|
* of the tree. If no specific
|
|
@@ -1778,26 +1898,26 @@ export class BinaryTree<
|
|
|
1778
1898
|
* @returns The function `_dfs` returns an array of the return type of the callback function provided
|
|
1779
1899
|
* as input.
|
|
1780
1900
|
*/
|
|
1781
|
-
protected _dfs<C extends NodeCallback<OptNodeOrNull<
|
|
1901
|
+
protected _dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
|
|
1782
1902
|
callback: C = this._DEFAULT_NODE_CALLBACK as C,
|
|
1783
1903
|
pattern: DFSOrderPattern = 'IN',
|
|
1784
|
-
startNode: BTNRep<K, V,
|
|
1904
|
+
startNode: BTNRep<K, V, BinaryTreeNode<K, V>> = this._root,
|
|
1785
1905
|
iterationType: IterationType = this.iterationType,
|
|
1786
1906
|
includeNull = false,
|
|
1787
|
-
shouldVisitLeft: (node: OptNodeOrNull<
|
|
1788
|
-
shouldVisitRight: (node: OptNodeOrNull<
|
|
1789
|
-
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 => {
|
|
1790
1910
|
if (includeNull) return this.isRealNodeOrNull(node);
|
|
1791
1911
|
return this.isRealNode(node);
|
|
1792
1912
|
},
|
|
1793
|
-
shouldProcessRoot: (node: OptNodeOrNull<
|
|
1913
|
+
shouldProcessRoot: (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => boolean = node => this.isRealNodeOrNull(node)
|
|
1794
1914
|
): ReturnType<C>[] {
|
|
1795
1915
|
startNode = this.ensureNode(startNode);
|
|
1796
1916
|
if (!startNode) return [];
|
|
1797
1917
|
const ans: ReturnType<C>[] = [];
|
|
1798
1918
|
|
|
1799
1919
|
if (iterationType === 'RECURSIVE') {
|
|
1800
|
-
const dfs = (node: OptNodeOrNull<
|
|
1920
|
+
const dfs = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => {
|
|
1801
1921
|
if (!shouldVisitRoot(node)) return;
|
|
1802
1922
|
|
|
1803
1923
|
const visitLeft = () => {
|
|
@@ -1828,15 +1948,15 @@ export class BinaryTree<
|
|
|
1828
1948
|
|
|
1829
1949
|
dfs(startNode);
|
|
1830
1950
|
} else {
|
|
1831
|
-
const stack: DFSStackItem<
|
|
1951
|
+
const stack: DFSStackItem<BinaryTreeNode<K, V>>[] = [{ opt: DFSOperation.VISIT, node: startNode }];
|
|
1832
1952
|
|
|
1833
|
-
const pushLeft = (cur: DFSStackItem<
|
|
1953
|
+
const pushLeft = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {
|
|
1834
1954
|
if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });
|
|
1835
1955
|
};
|
|
1836
|
-
const pushRight = (cur: DFSStackItem<
|
|
1956
|
+
const pushRight = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {
|
|
1837
1957
|
if (shouldVisitRight(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });
|
|
1838
1958
|
};
|
|
1839
|
-
const pushRoot = (cur: DFSStackItem<
|
|
1959
|
+
const pushRoot = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {
|
|
1840
1960
|
if (shouldVisitRoot(cur.node)) stack.push({ opt: DFSOperation.PROCESS, node: cur.node });
|
|
1841
1961
|
};
|
|
1842
1962
|
|
|
@@ -1890,8 +2010,8 @@ export class BinaryTree<
|
|
|
1890
2010
|
if (!node) return;
|
|
1891
2011
|
|
|
1892
2012
|
if (this.iterationType === 'ITERATIVE') {
|
|
1893
|
-
const stack: OptNodeOrNull<
|
|
1894
|
-
let current: OptNodeOrNull<
|
|
2013
|
+
const stack: OptNodeOrNull<BinaryTreeNode<K, V>>[] = [];
|
|
2014
|
+
let current: OptNodeOrNull<BinaryTreeNode<K, V>> = node;
|
|
1895
2015
|
|
|
1896
2016
|
while (current || stack.length > 0) {
|
|
1897
2017
|
while (this.isRealNode(current)) {
|
|
@@ -1934,7 +2054,7 @@ export class BinaryTree<
|
|
|
1934
2054
|
* information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
|
|
1935
2055
|
* elements:
|
|
1936
2056
|
*/
|
|
1937
|
-
protected _displayAux(node: OptNodeOrNull<
|
|
2057
|
+
protected _displayAux(node: OptNodeOrNull<BinaryTreeNode<K, V>>, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
|
1938
2058
|
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1939
2059
|
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
1940
2060
|
|
|
@@ -2002,24 +2122,27 @@ export class BinaryTree<
|
|
|
2002
2122
|
}
|
|
2003
2123
|
}
|
|
2004
2124
|
|
|
2005
|
-
protected _DEFAULT_NODE_CALLBACK = (node: OptNodeOrNull<
|
|
2125
|
+
protected _DEFAULT_NODE_CALLBACK = (node: OptNodeOrNull<BinaryTreeNode<K, V>>) => (node ? node.key : undefined);
|
|
2006
2126
|
|
|
2007
2127
|
/**
|
|
2008
2128
|
* Time Complexity: O(1)
|
|
2009
2129
|
* Space Complexity: O(1)
|
|
2010
2130
|
*
|
|
2011
2131
|
* The _swapProperties function swaps key and value properties between two nodes in a binary tree.
|
|
2012
|
-
* @param {BTNRep<K, V,
|
|
2132
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} srcNode - The `srcNode` parameter in the
|
|
2013
2133
|
* `_swapProperties` method can be either a BTNRep object containing key and value
|
|
2014
2134
|
* properties, or it can be of type R.
|
|
2015
|
-
* @param {BTNRep<K, V,
|
|
2135
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>>} destNode - The `destNode` parameter in the
|
|
2016
2136
|
* `_swapProperties` method represents the node or entry where the properties will be swapped with
|
|
2017
|
-
* 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
|
|
2018
2138
|
* both `srcNode
|
|
2019
2139
|
* @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
|
|
2020
2140
|
* with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
|
|
2021
2141
|
*/
|
|
2022
|
-
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 {
|
|
2023
2146
|
srcNode = this.ensureNode(srcNode);
|
|
2024
2147
|
destNode = this.ensureNode(destNode);
|
|
2025
2148
|
|
|
@@ -2045,16 +2168,16 @@ export class BinaryTree<
|
|
|
2045
2168
|
* Space Complexity: O(1)
|
|
2046
2169
|
*
|
|
2047
2170
|
* The _replaceNode function replaces an old node with a new node in a binary tree structure.
|
|
2048
|
-
* @param {
|
|
2171
|
+
* @param {BinaryTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that you want to replace in a
|
|
2049
2172
|
* tree data structure.
|
|
2050
|
-
* @param {
|
|
2173
|
+
* @param {BinaryTreeNode<K, V>} newNode - The `newNode` parameter in the `_replaceNode` function represents the node
|
|
2051
2174
|
* that will replace the `oldNode` in a tree data structure. This function is responsible for
|
|
2052
2175
|
* updating the parent, left child, right child, and root (if necessary) references when replacing a
|
|
2053
2176
|
* node in the tree.
|
|
2054
2177
|
* @returns The method `_replaceNode` is returning the `newNode` that was passed as a parameter after
|
|
2055
2178
|
* replacing the `oldNode` with it in the binary tree structure.
|
|
2056
2179
|
*/
|
|
2057
|
-
protected _replaceNode(oldNode:
|
|
2180
|
+
protected _replaceNode(oldNode: BinaryTreeNode<K, V>, newNode: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {
|
|
2058
2181
|
if (oldNode.parent) {
|
|
2059
2182
|
if (oldNode.parent.left === oldNode) {
|
|
2060
2183
|
oldNode.parent.left = newNode;
|
|
@@ -2078,10 +2201,10 @@ export class BinaryTree<
|
|
|
2078
2201
|
*
|
|
2079
2202
|
* The function _setRoot sets the root node of a data structure while updating the parent reference
|
|
2080
2203
|
* of the previous root node.
|
|
2081
|
-
* @param v - The parameter `v` in the `_setRoot` method is of type `OptNodeOrNull<
|
|
2082
|
-
* 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`.
|
|
2083
2206
|
*/
|
|
2084
|
-
protected _setRoot(v: OptNodeOrNull<
|
|
2207
|
+
protected _setRoot(v: OptNodeOrNull<BinaryTreeNode<K, V>>) {
|
|
2085
2208
|
if (v) {
|
|
2086
2209
|
v.parent = undefined;
|
|
2087
2210
|
}
|
|
@@ -2094,34 +2217,29 @@ export class BinaryTree<
|
|
|
2094
2217
|
*
|
|
2095
2218
|
* The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
|
|
2096
2219
|
* predicate function for a binary tree node.
|
|
2097
|
-
* @param {BTNRep<K, V,
|
|
2220
|
+
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
|
|
2098
2221
|
* `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
|
|
2099
|
-
* parameter `
|
|
2222
|
+
* parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be
|
|
2100
2223
|
* used for filtering nodes in a binary tree.
|
|
2101
|
-
* @returns A NodePredicate<
|
|
2224
|
+
* @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.
|
|
2102
2225
|
*/
|
|
2103
2226
|
protected _ensurePredicate(
|
|
2104
|
-
|
|
2105
|
-
): NodePredicate<
|
|
2106
|
-
if (
|
|
2107
|
-
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);
|
|
2108
2231
|
|
|
2109
|
-
if (this._isPredicate(
|
|
2232
|
+
if (this._isPredicate(keyNodeEntryOrPredicate)) return keyNodeEntryOrPredicate;
|
|
2110
2233
|
|
|
2111
|
-
if (this.isRealNode(
|
|
2234
|
+
if (this.isRealNode(keyNodeEntryOrPredicate))
|
|
2235
|
+
return (node: BinaryTreeNode<K, V>) => node === keyNodeEntryOrPredicate;
|
|
2112
2236
|
|
|
2113
|
-
if (this.isEntry(
|
|
2114
|
-
const [key] =
|
|
2115
|
-
return (node:
|
|
2237
|
+
if (this.isEntry(keyNodeEntryOrPredicate)) {
|
|
2238
|
+
const [key] = keyNodeEntryOrPredicate;
|
|
2239
|
+
return (node: BinaryTreeNode<K, V>) => node.key === key;
|
|
2116
2240
|
}
|
|
2117
2241
|
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
if (this._toEntryFn) {
|
|
2121
|
-
const [key] = this._toEntryFn(keyNodeEntryRawOrPredicate);
|
|
2122
|
-
return (node: NODE) => node.key === key;
|
|
2123
|
-
}
|
|
2124
|
-
return (node: NODE) => node.key === keyNodeEntryRawOrPredicate;
|
|
2242
|
+
return (node: BinaryTreeNode<K, V>) => node.key === keyNodeEntryOrPredicate;
|
|
2125
2243
|
}
|
|
2126
2244
|
|
|
2127
2245
|
/**
|
|
@@ -2131,12 +2249,12 @@ export class BinaryTree<
|
|
|
2131
2249
|
* The function `_isPredicate` checks if a given parameter is a function.
|
|
2132
2250
|
* @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type
|
|
2133
2251
|
* of value. In this context, the function `_isPredicate` is checking if `p` is a function that
|
|
2134
|
-
* satisfies the type `NodePredicate<
|
|
2252
|
+
* satisfies the type `NodePredicate<BinaryTreeNode<K, V>>`.
|
|
2135
2253
|
* @returns The function is checking if the input `p` is a function and returning a boolean value
|
|
2136
2254
|
* based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
|
|
2137
2255
|
* predicate function for a binary tree node. If `p` is not a function, it will return `false`.
|
|
2138
2256
|
*/
|
|
2139
|
-
protected _isPredicate(p: any): p is NodePredicate<
|
|
2257
|
+
protected _isPredicate(p: any): p is NodePredicate<BinaryTreeNode<K, V>> {
|
|
2140
2258
|
return typeof p === 'function';
|
|
2141
2259
|
}
|
|
2142
2260
|
|
|
@@ -2144,32 +2262,24 @@ export class BinaryTree<
|
|
|
2144
2262
|
* Time Complexity: O(1)
|
|
2145
2263
|
* Space Complexity: O(1)
|
|
2146
2264
|
*
|
|
2147
|
-
* The function `
|
|
2265
|
+
* The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,
|
|
2148
2266
|
* entry, raw data, or null/undefined.
|
|
2149
|
-
* @param {BTNRep<K, V,
|
|
2150
|
-
* TypeScript method that takes in a parameter `
|
|
2151
|
-
* where `BTNRep` is a generic type with keys `K`, `V`, and `
|
|
2152
|
-
* @returns 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`
|
|
2153
2271
|
* parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
|
|
2154
2272
|
* the conditions checked in the method.
|
|
2155
2273
|
*/
|
|
2156
|
-
protected
|
|
2157
|
-
if (
|
|
2158
|
-
if (
|
|
2159
|
-
if (
|
|
2160
|
-
if (this.isNode(
|
|
2161
|
-
|
|
2162
|
-
if (this.isEntry(
|
|
2163
|
-
|
|
2164
|
-
if (this.isRaw(keyNodeEntryOrRaw)) {
|
|
2165
|
-
if (this._toEntryFn) {
|
|
2166
|
-
const [key] = this._toEntryFn(keyNodeEntryOrRaw);
|
|
2167
|
-
return key;
|
|
2168
|
-
}
|
|
2169
|
-
return;
|
|
2170
|
-
}
|
|
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];
|
|
2171
2281
|
|
|
2172
|
-
return
|
|
2282
|
+
return keyNodeOrEntry;
|
|
2173
2283
|
}
|
|
2174
2284
|
|
|
2175
2285
|
/**
|
|
@@ -2193,6 +2303,9 @@ export class BinaryTree<
|
|
|
2193
2303
|
}
|
|
2194
2304
|
|
|
2195
2305
|
/**
|
|
2306
|
+
* Time Complexity: O(1)
|
|
2307
|
+
* Space Complexity: O(1)
|
|
2308
|
+
*
|
|
2196
2309
|
* The _clearNodes function sets the root node to undefined and resets the size to 0.
|
|
2197
2310
|
*/
|
|
2198
2311
|
protected _clearNodes() {
|
|
@@ -2201,6 +2314,9 @@ export class BinaryTree<
|
|
|
2201
2314
|
}
|
|
2202
2315
|
|
|
2203
2316
|
/**
|
|
2317
|
+
* Time Complexity: O(1)
|
|
2318
|
+
* Space Complexity: O(1)
|
|
2319
|
+
*
|
|
2204
2320
|
* The _clearValues function clears all values stored in the _store object.
|
|
2205
2321
|
*/
|
|
2206
2322
|
protected _clearValues() {
|