data-structure-typed 1.15.2 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +24 -24
  2. package/dist/data-structures/heap/heap.d.ts +30 -15
  3. package/dist/data-structures/heap/heap.js +60 -15
  4. package/dist/data-structures/heap/max-heap.d.ts +3 -3
  5. package/dist/data-structures/heap/min-heap.d.ts +3 -3
  6. package/dist/data-structures/index.d.ts +1 -0
  7. package/dist/data-structures/index.js +1 -0
  8. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +195 -68
  9. package/dist/data-structures/linked-list/doubly-linked-list.js +456 -244
  10. package/dist/data-structures/linked-list/singly-linked-list.d.ts +126 -241
  11. package/dist/data-structures/linked-list/singly-linked-list.js +331 -628
  12. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +4 -5
  13. package/dist/data-structures/priority-queue/max-priority-queue.js +30 -6
  14. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +4 -5
  15. package/dist/data-structures/priority-queue/min-priority-queue.js +31 -6
  16. package/dist/data-structures/priority-queue/priority-queue.d.ts +13 -2
  17. package/dist/data-structures/priority-queue/priority-queue.js +28 -22
  18. package/dist/data-structures/tree/index.d.ts +1 -0
  19. package/dist/data-structures/tree/index.js +17 -0
  20. package/dist/data-structures/tree/tree.d.ts +9 -0
  21. package/dist/data-structures/tree/tree.js +52 -0
  22. package/dist/data-structures/types/binary-tree.d.ts +0 -5
  23. package/dist/data-structures/types/heap.d.ts +0 -4
  24. package/dist/utils/types/utils.d.ts +1 -0
  25. package/docs/.nojekyll +1 -0
  26. package/docs/assets/highlight.css +92 -0
  27. package/docs/assets/main.js +58 -0
  28. package/docs/assets/search.js +1 -0
  29. package/docs/assets/style.css +1367 -0
  30. package/docs/classes/AVLTree.html +2191 -0
  31. package/docs/classes/AVLTreeNode.html +573 -0
  32. package/docs/classes/AaTree.html +149 -0
  33. package/docs/classes/AbstractEdge.html +268 -0
  34. package/docs/classes/AbstractGraph.html +926 -0
  35. package/docs/classes/AbstractVertex.html +214 -0
  36. package/docs/classes/ArrayDeque.html +416 -0
  37. package/docs/classes/BST.html +2037 -0
  38. package/docs/classes/BSTNode.html +569 -0
  39. package/docs/classes/BTree.html +149 -0
  40. package/docs/classes/BinaryIndexedTree.html +288 -0
  41. package/docs/classes/BinaryTree.html +1826 -0
  42. package/docs/classes/BinaryTreeNode.html +532 -0
  43. package/docs/classes/Character.html +197 -0
  44. package/docs/classes/CoordinateMap.html +468 -0
  45. package/docs/classes/CoordinateSet.html +429 -0
  46. package/docs/classes/Deque.html +897 -0
  47. package/docs/classes/DirectedEdge.html +353 -0
  48. package/docs/classes/DirectedGraph.html +1242 -0
  49. package/docs/classes/DirectedVertex.html +225 -0
  50. package/docs/classes/DoublyLinkedList.html +891 -0
  51. package/docs/classes/DoublyLinkedListNode.html +274 -0
  52. package/docs/classes/Heap.html +481 -0
  53. package/docs/classes/HeapItem.html +232 -0
  54. package/docs/classes/Matrix2D.html +479 -0
  55. package/docs/classes/MatrixNTI2D.html +217 -0
  56. package/docs/classes/MaxHeap.html +499 -0
  57. package/docs/classes/MaxPriorityQueue.html +808 -0
  58. package/docs/classes/MinHeap.html +500 -0
  59. package/docs/classes/MinPriorityQueue.html +810 -0
  60. package/docs/classes/Navigator.html +290 -0
  61. package/docs/classes/ObjectDeque.html +422 -0
  62. package/docs/classes/PriorityQueue.html +732 -0
  63. package/docs/classes/Queue.html +369 -0
  64. package/docs/classes/RBTree.html +149 -0
  65. package/docs/classes/SegmentTree.html +344 -0
  66. package/docs/classes/SegmentTreeNode.html +417 -0
  67. package/docs/classes/SinglyLinkedList.html +718 -0
  68. package/docs/classes/SinglyLinkedListNode.html +247 -0
  69. package/docs/classes/SplayTree.html +149 -0
  70. package/docs/classes/Stack.html +345 -0
  71. package/docs/classes/TreeMultiSet.html +2035 -0
  72. package/docs/classes/TreeNode.html +235 -0
  73. package/docs/classes/Trie.html +349 -0
  74. package/docs/classes/TrieNode.html +257 -0
  75. package/docs/classes/TwoThreeTree.html +149 -0
  76. package/docs/classes/UndirectedEdge.html +312 -0
  77. package/docs/classes/UndirectedGraph.html +1079 -0
  78. package/docs/classes/UndirectedVertex.html +225 -0
  79. package/docs/classes/Vector2D.html +782 -0
  80. package/docs/enums/CP.html +158 -0
  81. package/docs/enums/FamilyPosition.html +158 -0
  82. package/docs/enums/LoopType.html +159 -0
  83. package/docs/index.html +493 -0
  84. package/docs/interfaces/AVLTreeDeleted.html +160 -0
  85. package/docs/interfaces/HeapOptions.html +166 -0
  86. package/docs/interfaces/IDirectedGraph.html +242 -0
  87. package/docs/interfaces/IGraph.html +426 -0
  88. package/docs/interfaces/NavigatorParams.html +196 -0
  89. package/docs/interfaces/PriorityQueueOptions.html +167 -0
  90. package/docs/modules.html +216 -0
  91. package/docs/types/BSTComparator.html +139 -0
  92. package/docs/types/BSTDeletedResult.html +136 -0
  93. package/docs/types/BinaryTreeDeleted.html +136 -0
  94. package/docs/types/BinaryTreeNodeId.html +124 -0
  95. package/docs/types/BinaryTreeNodePropertyName.html +124 -0
  96. package/docs/types/DFSOrderPattern.html +124 -0
  97. package/docs/types/DijkstraResult.html +144 -0
  98. package/docs/types/Direction.html +124 -0
  99. package/docs/types/DoublyLinkedListGetBy.html +124 -0
  100. package/docs/types/NodeOrPropertyName.html +124 -0
  101. package/docs/types/PriorityQueueComparator.html +144 -0
  102. package/docs/types/PriorityQueueDFSOrderPattern.html +124 -0
  103. package/docs/types/ResultByProperty.html +129 -0
  104. package/docs/types/ResultsByProperty.html +129 -0
  105. package/docs/types/SegmentTreeNodeVal.html +124 -0
  106. package/docs/types/SpecifyOptional.html +131 -0
  107. package/docs/types/Thunk.html +132 -0
  108. package/docs/types/ToThunkFn.html +132 -0
  109. package/docs/types/TopologicalStatus.html +124 -0
  110. package/docs/types/TreeMultiSetDeletedResult.html +136 -0
  111. package/docs/types/TrlAsyncFn.html +137 -0
  112. package/docs/types/TrlFn.html +137 -0
  113. package/docs/types/Turning.html +124 -0
  114. package/docs/types/VertexId.html +124 -0
  115. package/{tests/unit/data-structures/binary-tree → notes}/bst.test.ts +37 -50
  116. package/notes/note.md +23 -0
  117. package/package.json +1 -3
  118. package/.idea/data-structure-typed.iml +0 -14
  119. package/.idea/modules.xml +0 -8
  120. package/.idea/vcs.xml +0 -6
  121. package/src/assets/complexities-diff.jpg +0 -0
  122. package/src/assets/data-structure-complexities.jpg +0 -0
  123. package/src/assets/logo.png +0 -0
  124. package/src/assets/overview-diagram-of-data-structures.png +0 -0
  125. package/src/data-structures/binary-tree/aa-tree.ts +0 -3
  126. package/src/data-structures/binary-tree/avl-tree.ts +0 -293
  127. package/src/data-structures/binary-tree/b-tree.ts +0 -3
  128. package/src/data-structures/binary-tree/binary-indexed-tree.ts +0 -69
  129. package/src/data-structures/binary-tree/binary-tree.ts +0 -1492
  130. package/src/data-structures/binary-tree/bst.ts +0 -497
  131. package/src/data-structures/binary-tree/diagrams/avl-tree-inserting.gif +0 -0
  132. package/src/data-structures/binary-tree/diagrams/bst-rotation.gif +0 -0
  133. package/src/data-structures/binary-tree/diagrams/segment-tree.png +0 -0
  134. package/src/data-structures/binary-tree/index.ts +0 -11
  135. package/src/data-structures/binary-tree/rb-tree.ts +0 -3
  136. package/src/data-structures/binary-tree/segment-tree.ts +0 -267
  137. package/src/data-structures/binary-tree/splay-tree.ts +0 -3
  138. package/src/data-structures/binary-tree/tree-multiset.ts +0 -53
  139. package/src/data-structures/binary-tree/two-three-tree.ts +0 -3
  140. package/src/data-structures/diagrams/README.md +0 -5
  141. package/src/data-structures/graph/abstract-graph.ts +0 -958
  142. package/src/data-structures/graph/diagrams/adjacency-list-pros-cons.jpg +0 -0
  143. package/src/data-structures/graph/diagrams/adjacency-list.jpg +0 -0
  144. package/src/data-structures/graph/diagrams/adjacency-matrix-pros-cons.jpg +0 -0
  145. package/src/data-structures/graph/diagrams/adjacency-matrix.jpg +0 -0
  146. package/src/data-structures/graph/diagrams/dfs-can-do.jpg +0 -0
  147. package/src/data-structures/graph/diagrams/edge-list-pros-cons.jpg +0 -0
  148. package/src/data-structures/graph/diagrams/edge-list.jpg +0 -0
  149. package/src/data-structures/graph/diagrams/max-flow.jpg +0 -0
  150. package/src/data-structures/graph/diagrams/mst.jpg +0 -0
  151. package/src/data-structures/graph/diagrams/tarjan-articulation-point-bridge.png +0 -0
  152. package/src/data-structures/graph/diagrams/tarjan-complicate-simple.png +0 -0
  153. package/src/data-structures/graph/diagrams/tarjan-strongly-connected-component.png +0 -0
  154. package/src/data-structures/graph/diagrams/tarjan.mp4 +0 -0
  155. package/src/data-structures/graph/diagrams/tarjan.webp +0 -0
  156. package/src/data-structures/graph/directed-graph.ts +0 -429
  157. package/src/data-structures/graph/index.ts +0 -3
  158. package/src/data-structures/graph/undirected-graph.ts +0 -259
  159. package/src/data-structures/hash/coordinate-map.ts +0 -74
  160. package/src/data-structures/hash/coordinate-set.ts +0 -63
  161. package/src/data-structures/hash/hash-table.ts +0 -1
  162. package/src/data-structures/hash/index.ts +0 -6
  163. package/src/data-structures/hash/pair.ts +0 -1
  164. package/src/data-structures/hash/tree-map.ts +0 -1
  165. package/src/data-structures/hash/tree-set.ts +0 -1
  166. package/src/data-structures/heap/heap.ts +0 -162
  167. package/src/data-structures/heap/index.ts +0 -3
  168. package/src/data-structures/heap/max-heap.ts +0 -31
  169. package/src/data-structures/heap/min-heap.ts +0 -34
  170. package/src/data-structures/index.ts +0 -13
  171. package/src/data-structures/linked-list/doubly-linked-list.ts +0 -365
  172. package/src/data-structures/linked-list/index.ts +0 -2
  173. package/src/data-structures/linked-list/singly-linked-list.ts +0 -757
  174. package/src/data-structures/linked-list/skip-linked-list.ts +0 -1
  175. package/src/data-structures/matrix/index.ts +0 -4
  176. package/src/data-structures/matrix/matrix.ts +0 -27
  177. package/src/data-structures/matrix/matrix2d.ts +0 -208
  178. package/src/data-structures/matrix/navigator.ts +0 -122
  179. package/src/data-structures/matrix/vector2d.ts +0 -316
  180. package/src/data-structures/priority-queue/index.ts +0 -3
  181. package/src/data-structures/priority-queue/max-priority-queue.ts +0 -24
  182. package/src/data-structures/priority-queue/min-priority-queue.ts +0 -24
  183. package/src/data-structures/priority-queue/priority-queue.ts +0 -349
  184. package/src/data-structures/queue/deque.ts +0 -251
  185. package/src/data-structures/queue/index.ts +0 -2
  186. package/src/data-structures/queue/queue.ts +0 -120
  187. package/src/data-structures/stack/index.ts +0 -1
  188. package/src/data-structures/stack/stack.ts +0 -98
  189. package/src/data-structures/trie/index.ts +0 -1
  190. package/src/data-structures/trie/trie.ts +0 -225
  191. package/src/data-structures/types/abstract-graph.ts +0 -51
  192. package/src/data-structures/types/avl-tree.ts +0 -6
  193. package/src/data-structures/types/binary-tree.ts +0 -15
  194. package/src/data-structures/types/bst.ts +0 -5
  195. package/src/data-structures/types/directed-graph.ts +0 -18
  196. package/src/data-structures/types/doubly-linked-list.ts +0 -1
  197. package/src/data-structures/types/heap.ts +0 -8
  198. package/src/data-structures/types/index.ts +0 -13
  199. package/src/data-structures/types/navigator.ts +0 -13
  200. package/src/data-structures/types/priority-queue.ts +0 -9
  201. package/src/data-structures/types/segment-tree.ts +0 -1
  202. package/src/data-structures/types/singly-linked-list.ts +0 -1
  203. package/src/data-structures/types/tree-multiset.ts +0 -3
  204. package/src/index.ts +0 -1
  205. package/src/utils/index.ts +0 -2
  206. package/src/utils/types/index.ts +0 -1
  207. package/src/utils/types/utils.ts +0 -4
  208. package/src/utils/utils.ts +0 -78
  209. package/tests/unit/data-structures/graph/abstract-graph.ts +0 -0
  210. package/tests/unit/data-structures/graph/directed-graph.test.ts +0 -492
  211. package/tests/unit/data-structures/graph/index.ts +0 -3
  212. package/tests/unit/data-structures/graph/undirected-graph.ts +0 -0
@@ -1,1492 +0,0 @@
1
- /**
2
- * data-structure-typed
3
- *
4
- * @author Tyler Zeng
5
- * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
- * @license MIT License
7
- */
8
-
9
- import {trampoline} from '../../utils';
10
- import type {
11
- BinaryTreeDeleted,
12
- BinaryTreeNodeId,
13
- BinaryTreeNodePropertyName,
14
- DFSOrderPattern,
15
- NodeOrPropertyName,
16
- ResultByProperty,
17
- ResultsByProperty
18
- } from '../types';
19
-
20
- /* This enumeration defines the position of a node within a family tree composed of three associated nodes, where 'root' represents the root node of the family tree, 'left' represents the left child node, and 'right' represents the right child node. */
21
- export enum FamilyPosition {root, left, right}
22
-
23
- /**
24
- * Enum representing different loop types.
25
- *
26
- * - `iterative`: Indicates the iterative loop type (with loops that use iterations).
27
- * - `recursive`: Indicates the recursive loop type (with loops that call themselves).
28
- */
29
- export enum LoopType { iterative = 1, recursive = 2}
30
-
31
- export class BinaryTreeNode<T> {
32
-
33
- constructor(id: BinaryTreeNodeId, val: T, count?: number) {
34
- this._id = id;
35
- this._val = val;
36
- this._count = count ?? 1;
37
- }
38
-
39
- protected _id: BinaryTreeNodeId;
40
-
41
- get id(): BinaryTreeNodeId {
42
- return this._id;
43
- }
44
-
45
- set id(v: BinaryTreeNodeId) {
46
- this._id = v;
47
- }
48
-
49
- protected _val: T;
50
- get val(): T {
51
- return this._val;
52
- }
53
-
54
- set val(v: T) {
55
- this._val = v;
56
- }
57
-
58
- protected _left?: BinaryTreeNode<T> | null;
59
-
60
- get left(): BinaryTreeNode<T> | null | undefined {
61
- return this._left;
62
- }
63
-
64
- set left(v: BinaryTreeNode<T> | null | undefined) {
65
- if (v) {
66
- v.parent = this;
67
- v.familyPosition = FamilyPosition.left;
68
- }
69
- this._left = v;
70
- }
71
-
72
- protected _right?: BinaryTreeNode<T> | null;
73
-
74
- get right(): BinaryTreeNode<T> | null | undefined {
75
- return this._right;
76
- }
77
-
78
- set right(v: BinaryTreeNode<T> | null | undefined) {
79
- if (v) {
80
- v.parent = this;
81
- v.familyPosition = FamilyPosition.right;
82
- }
83
- this._right = v;
84
- }
85
-
86
- protected _parent: BinaryTreeNode<T> | null | undefined;
87
-
88
- get parent(): BinaryTreeNode<T> | null | undefined {
89
- return this._parent;
90
- }
91
-
92
- set parent(v: BinaryTreeNode<T> | null | undefined) {
93
- this._parent = v;
94
- }
95
-
96
- protected _familyPosition: FamilyPosition = FamilyPosition.root;
97
-
98
- get familyPosition(): FamilyPosition {
99
- return this._familyPosition;
100
- }
101
-
102
- set familyPosition(v: FamilyPosition) {
103
- this._familyPosition = v;
104
- }
105
-
106
- protected _count = 1;
107
-
108
- get count(): number {
109
- return this._count;
110
- }
111
-
112
- set count(v: number) {
113
- this._count = v;
114
- }
115
-
116
- protected _height = 0;
117
-
118
- get height(): number {
119
- return this._height;
120
- }
121
-
122
- set height(v: number) {
123
- this._height = v;
124
- }
125
-
126
- /**
127
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
128
- */
129
- getId(): BinaryTreeNodeId {
130
- return this._id;
131
- }
132
-
133
- /**
134
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
135
- */
136
- getVal(): T {
137
- return this._val;
138
- }
139
-
140
- /**
141
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
142
- */
143
- getLeft(): BinaryTreeNode<T> | null | undefined {
144
- return this._left;
145
- }
146
-
147
- /**
148
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
149
- */
150
- getRight(): BinaryTreeNode<T> | null | undefined {
151
- return this._right;
152
- }
153
-
154
- /**
155
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
156
- */
157
- getParent(): BinaryTreeNode<T> | null | undefined {
158
- return this._parent;
159
- }
160
-
161
- /**
162
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
163
- */
164
- getFamilyPosition(): FamilyPosition {
165
- return this._familyPosition;
166
- }
167
-
168
- /**
169
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
170
- */
171
- getCount(): number {
172
- return this._count;
173
- }
174
-
175
- /**
176
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
177
- */
178
- getHeight(): number {
179
- return this._height;
180
- }
181
-
182
- swapLocation(swapNode: BinaryTreeNode<T>): BinaryTreeNode<T> {
183
- const {val, count, height} = swapNode;
184
- const tempNode = new BinaryTreeNode<T>(swapNode.id, val);
185
- tempNode.val = val;
186
- tempNode.count = count;
187
- tempNode.height = height;
188
-
189
- swapNode.id = this.id;
190
- swapNode.val = this.val;
191
- swapNode.count = this.count;
192
- swapNode.height = this.height;
193
-
194
- this.id = tempNode.id;
195
- this.val = tempNode.val;
196
- this.count = tempNode.count;
197
- this.height = tempNode.height;
198
- return swapNode;
199
- }
200
-
201
- clone(): BinaryTreeNode<T> {
202
- return new BinaryTreeNode<T>(this.id, this.val, this.count);
203
- }
204
- }
205
-
206
- export class BinaryTree<T> {
207
- protected _loopType: LoopType = LoopType.iterative;
208
- protected _visitedId: BinaryTreeNodeId[] = [];
209
- protected _visitedVal: Array<T> = [];
210
- protected _visitedNode: BinaryTreeNode<T>[] = [];
211
- protected _visitedCount: number[] = [];
212
- protected _visitedLeftSum: number[] = [];
213
- private readonly _autoIncrementId: boolean = false;
214
- private _maxId: number = -1;
215
- private readonly _isDuplicatedVal: boolean = false;
216
-
217
- /**
218
- * The constructor function accepts an optional options object and sets the values of loopType, autoIncrementId, and
219
- * isDuplicatedVal based on the provided options.
220
- * @param [options] - An optional object that can contain the following properties:
221
- */
222
- constructor(options?: {
223
- loopType?: LoopType,
224
- autoIncrementId?: boolean,
225
- isDuplicatedVal?: boolean
226
- }) {
227
- if (options !== undefined) {
228
- const {
229
- loopType = LoopType.iterative,
230
- autoIncrementId = false,
231
- isDuplicatedVal = false
232
- } = options;
233
- this._isDuplicatedVal = isDuplicatedVal;
234
- this._autoIncrementId = autoIncrementId;
235
- this._loopType = loopType;
236
- }
237
- }
238
-
239
- protected _root: BinaryTreeNode<T> | null = null;
240
-
241
- get root(): BinaryTreeNode<T> | null {
242
- return this._root;
243
- }
244
-
245
- protected set root(v: BinaryTreeNode<T> | null) {
246
- if (v) {
247
- v.parent = null;
248
- v.familyPosition = FamilyPosition.root;
249
- }
250
- this._root = v;
251
- }
252
-
253
- protected _size = 0;
254
-
255
- get size(): number {
256
- return this._size;
257
- }
258
-
259
- protected set size(v: number) {
260
- this._size = v;
261
- }
262
-
263
- protected _count = 0;
264
-
265
- get count(): number {
266
- return this._count;
267
- }
268
-
269
- protected set count(v: number) {
270
- this._count = v;
271
- }
272
-
273
- /**
274
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Getters (using the same name as the property) while utilizing separate method names for Setters.
275
- * @returns The method is returning either a BinaryTreeNode object of type T or null.
276
- */
277
- getRoot(): BinaryTreeNode<T> | null {
278
- return this._root;
279
- }
280
-
281
- /**
282
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
283
- */
284
- getSize(): number {
285
- return this._size;
286
- }
287
-
288
- /**
289
- * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
290
- */
291
- getCount(): number {
292
- return this._count;
293
- }
294
-
295
- /**
296
- * The function creates a new binary tree node with the given id, value, and count, or returns null if the value is
297
- * null.
298
- * @param {BinaryTreeNodeId} id - The `id` parameter is the identifier for the binary tree node. It is of type
299
- * `BinaryTreeNodeId`, which could be a string or a number, depending on how you want to identify your nodes.
300
- * @param {T | null} val - The `val` parameter represents the value to be stored in the binary tree node. It can be of
301
- * any type `T` or `null`.
302
- * @param {number} [count] - The count parameter is an optional parameter that represents the number of occurrences of
303
- * the value in the binary tree node. It is of type number.
304
- * @returns The function `createNode` returns a `BinaryTreeNode<T>` object if the `val` parameter is not null.
305
- * Otherwise, it returns null.
306
- */
307
- createNode(id: BinaryTreeNodeId, val: T | null, count?: number): BinaryTreeNode<T> | null {
308
- return val !== null ? new BinaryTreeNode(id, val, count) : null;
309
- }
310
-
311
- /**
312
- * The clear function resets the state of an object by setting its properties to their initial values.
313
- */
314
- clear() {
315
- this.root = null;
316
- this.size = 0;
317
- this.count = 0;
318
- this._maxId = -1;
319
- }
320
-
321
- /**
322
- * The function checks if the size of an object is equal to zero and returns a boolean value.
323
- * @returns A boolean value indicating whether the size of the object is 0 or not.
324
- */
325
- isEmpty(): boolean {
326
- return this.size === 0;
327
- }
328
-
329
- /**
330
- * The `add` function inserts a new node with a given ID and value into a binary tree, updating the count if the node
331
- * already exists.
332
- * @param {BinaryTreeNodeId} id - The id parameter is the identifier of the binary tree node. It is used to uniquely
333
- * identify each node in the binary tree.
334
- * @param {T} val - The value to be inserted into the binary tree.
335
- * @param {number} [count] - The `count` parameter is an optional parameter that specifies the number of times the
336
- * value should be inserted into the binary tree. If not provided, it defaults to 1.
337
- * @returns The function `add` returns a `BinaryTreeNode<T>` object if a new node is inserted, or `null` if no new node
338
- * is inserted, or `undefined` if the insertion fails.
339
- */
340
- add(id: BinaryTreeNodeId, val: T, count?: number): BinaryTreeNode<T> | null | undefined {
341
- count = count ?? 1;
342
-
343
- const _bfs = (root: BinaryTreeNode<T>, newNode: BinaryTreeNode<T> | null): BinaryTreeNode<T> | undefined | null => {
344
- const queue: Array<BinaryTreeNode<T> | null> = [root];
345
- while (queue.length > 0) {
346
- const cur = queue.shift();
347
- if (cur) {
348
- const inserted = this.addTo(newNode, cur);
349
- if (inserted !== undefined) return inserted;
350
- if (cur.left) queue.push(cur.left);
351
- if (cur.right) queue.push(cur.right);
352
- } else return;
353
- }
354
- return;
355
- };
356
-
357
- let inserted: BinaryTreeNode<T> | null | undefined;
358
- const needInsert = val !== null ? new BinaryTreeNode<T>(id, val, count) : null;
359
- const existNode = val !== null ? this.get(id, 'id') : null;
360
- if (this.root) {
361
- if (existNode) {
362
- existNode.count += count;
363
- existNode.val = val;
364
- if (needInsert !== null) {
365
- this.count += count;
366
- inserted = existNode;
367
- }
368
- } else {
369
- inserted = _bfs(this.root, needInsert);
370
- }
371
- } else {
372
- this.root = val !== null ? new BinaryTreeNode<T>(id, val, count) : null;
373
- if (needInsert !== null) {
374
- this.size = 1;
375
- this.count = count;
376
- }
377
- inserted = this.root;
378
- }
379
- return inserted;
380
- }
381
-
382
- /**
383
- * The function inserts a new node into a binary tree as the left or right child of a given parent node.
384
- * @param {BinaryTreeNode<T> | null} newNode - The `newNode` parameter is an instance of the `BinaryTreeNode` class or
385
- * `null`. It represents the node that needs to be inserted into the binary tree.
386
- * @param parent - The `parent` parameter is a BinaryTreeNode object representing the parent node to which the new node
387
- * will be inserted as a child.
388
- * @returns The method returns the newly inserted node, either as the left child or the right child of the parent node.
389
- */
390
- addTo(newNode: BinaryTreeNode<T> | null, parent: BinaryTreeNode<T>) {
391
- if (parent) {
392
- if (parent.left === undefined) {
393
- if (newNode) {
394
- newNode.parent = parent;
395
- newNode.familyPosition = FamilyPosition.left;
396
- }
397
- parent.left = newNode;
398
- if (newNode !== null) {
399
- this.size++;
400
- this.count += newNode?.count ?? 0;
401
- }
402
-
403
- return parent.left;
404
- } else if (parent.right === undefined) {
405
- if (newNode) {
406
- newNode.parent = parent;
407
- newNode.familyPosition = FamilyPosition.right;
408
- }
409
- parent.right = newNode;
410
- if (newNode !== null) {
411
- this.size++;
412
- this.count += newNode?.count ?? 0;
413
- }
414
- return parent.right;
415
- } else {
416
- return;
417
- }
418
- } else {
419
- return;
420
- }
421
- }
422
-
423
- /**
424
- * The `addMany` function inserts multiple items into a binary tree and returns an array of the inserted nodes or
425
- * null/undefined values.
426
- * @param {T[] | BinaryTreeNode<T>[]} data - The `data` parameter can be either an array of elements of type `T` or an
427
- * array of `BinaryTreeNode<T>` objects.
428
- * @returns The function `addMany` returns an array of `BinaryTreeNode<T>`, `null`, or `undefined` values.
429
- */
430
- addMany(data: T[] | BinaryTreeNode<T>[]): (BinaryTreeNode<T> | null | undefined)[] {
431
- const inserted: (BinaryTreeNode<T> | null | undefined)[] = [];
432
- const map: Map<T | BinaryTreeNode<T>, number> = new Map();
433
-
434
- if (!this._isDuplicatedVal) {
435
- for (const i of data) map.set(i, (map.get(i) ?? 0) + 1);
436
- }
437
-
438
- for (const item of data) {
439
- const count = this._isDuplicatedVal ? 1 : map.get(item);
440
-
441
- if (item instanceof BinaryTreeNode) {
442
- inserted.push(this.add(item.id, item.val, item.count));
443
- } else if (typeof item === 'number' && !this._autoIncrementId) {
444
- if (!this._isDuplicatedVal) {
445
- if (map.get(item) !== undefined) {
446
- inserted.push(this.add(item, item, count));
447
- map.delete(item);
448
- }
449
- } else {
450
- inserted.push(this.add(item, item, 1));
451
- }
452
- } else {
453
- if (item !== null) {
454
- if (!this._isDuplicatedVal) {
455
- if (map.get(item) !== undefined) {
456
- inserted.push(this.add(++this._maxId, item, count));
457
- map.delete(item);
458
- }
459
- } else {
460
- inserted.push(this.add(++this._maxId, item, 1));
461
- }
462
- } else {
463
- inserted.push(this.add(Number.MAX_SAFE_INTEGER, item, 0));
464
- }
465
- }
466
- }
467
- return inserted;
468
- }
469
-
470
- /**
471
- * The `fill` function clears the current data and inserts new data, returning a boolean indicating if the insertion
472
- * was successful.
473
- * @param {T[] | BinaryTreeNode<T>[]} data - The `data` parameter can be either an array of elements of type `T` or an
474
- * array of `BinaryTreeNode<T>` objects.
475
- * @returns The method is returning a boolean value.
476
- */
477
- fill(data: T[] | BinaryTreeNode<T>[]): boolean {
478
- this.clear();
479
- return data.length === this.addMany(data).length;
480
- }
481
-
482
- /**
483
- * The function removes a node from a binary tree and returns information about the deleted node.
484
- * @param {BinaryTreeNodeId} id - The `id` parameter is the identifier of the binary tree node that you want to remove.
485
- * It is of type `BinaryTreeNodeId`.
486
- * @param {boolean} [ignoreCount] - The `ignoreCount` parameter is an optional boolean parameter that determines
487
- * whether to ignore the count of the node being removed. If `ignoreCount` is set to `true`, the count of the node will
488
- * not be decremented and the overall count of the binary tree will not be updated. If `
489
- * @returns An array of objects is being returned. Each object in the array has two properties: "deleted" and
490
- * "needBalanced". The "deleted" property contains the deleted node or undefined if no node was deleted. The
491
- * "needBalanced" property is always null.
492
- */
493
- remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeleted<T>[] {
494
- const nodes = this.getNodes(id, 'id', true);
495
- let node: BinaryTreeNode<T> | null | undefined = nodes[0];
496
-
497
- if (!node) node = undefined;
498
- else if (node.count > 1 && !ignoreCount) {
499
- node.count--;
500
- this.count--;
501
- } else if (node instanceof BinaryTreeNode) {
502
- const [subSize, subCount] = this.getSubTreeSizeAndCount(node);
503
-
504
- switch (node.familyPosition) {
505
- case 0:
506
- this.size -= subSize;
507
- this.count -= subCount;
508
- node = undefined;
509
- break;
510
- case 1:
511
- if (node.parent) {
512
- this.size -= subSize;
513
- this.count -= subCount;
514
- node.parent.left = null;
515
- }
516
- break;
517
- case 2:
518
- if (node.parent) {
519
- this.size -= subSize;
520
- this.count -= subCount;
521
- node.parent.right = null;
522
- }
523
- break;
524
- }
525
- }
526
- return [{deleted: node, needBalanced: null}];
527
- }
528
-
529
- /**
530
- * The function calculates the depth of a binary tree node by traversing its parent nodes.
531
- * @param node - BinaryTreeNode<T> - This is the node for which we want to calculate the depth. It is a generic type,
532
- * meaning it can represent any type of data that we want to store in the node.
533
- * @returns The depth of the given binary tree node.
534
- */
535
- getDepth(node: BinaryTreeNode<T>): number {
536
- let depth = 0;
537
- while (node.parent) {
538
- depth++;
539
- node = node.parent;
540
- }
541
- return depth;
542
- }
543
-
544
- /**
545
- * The `getHeight` function calculates the maximum height of a binary tree using either a recursive or iterative
546
- * approach.
547
- * @param {BinaryTreeNode<T> | null} [beginRoot] - The `beginRoot` parameter is an optional parameter of type
548
- * `BinaryTreeNode<T> | null`. It represents the starting node from which to calculate the height of the binary tree.
549
- * If no value is provided for `beginRoot`, the function will use the `root` property of the class instance as
550
- * @returns the height of the binary tree.
551
- */
552
- getHeight(beginRoot?: BinaryTreeNode<T> | null): number {
553
- beginRoot = beginRoot ?? this.root;
554
- if (!beginRoot) return -1;
555
-
556
- if (this._loopType === LoopType.recursive) {
557
- const _getMaxHeight = (cur: BinaryTreeNode<T> | null | undefined): number => {
558
- if (!cur) return -1;
559
- const leftHeight = _getMaxHeight(cur.left);
560
- const rightHeight = _getMaxHeight(cur.right);
561
- return Math.max(leftHeight, rightHeight) + 1;
562
- };
563
-
564
- return _getMaxHeight(beginRoot);
565
- } else {
566
- const stack: BinaryTreeNode<T>[] = [];
567
- let node: BinaryTreeNode<T> | null | undefined = beginRoot, last: BinaryTreeNode<T> | null = null;
568
- const depths: Map<BinaryTreeNode<T>, number> = new Map();
569
-
570
- while (stack.length > 0 || node) {
571
- if (node) {
572
- stack.push(node);
573
- node = node.left;
574
- } else {
575
- node = stack[stack.length - 1]
576
- if (!node.right || last === node.right) {
577
- node = stack.pop();
578
- if (node) {
579
- const leftHeight = node.left ? depths.get(node.left) ?? -1 : -1;
580
- const rightHeight = node.right ? depths.get(node.right) ?? -1 : -1;
581
- depths.set(node, 1 + Math.max(leftHeight, rightHeight));
582
- last = node;
583
- node = null;
584
- }
585
- } else node = node.right
586
- }
587
- }
588
-
589
- return depths.get(beginRoot) ?? -1;
590
- }
591
- }
592
-
593
- /**
594
- * The `getMinHeight` function calculates the minimum height of a binary tree using either a recursive or iterative
595
- * approach.
596
- * @param {BinaryTreeNode<T> | null} [beginRoot] - The `beginRoot` parameter is an optional parameter of type
597
- * `BinaryTreeNode<T> | null`. It represents the starting node from which to calculate the minimum height of the binary
598
- * tree. If no value is provided for `beginRoot`, the function will use the root node of the binary tree.
599
- * @returns The function `getMinHeight` returns the minimum height of the binary tree.
600
- */
601
- getMinHeight(beginRoot?: BinaryTreeNode<T> | null): number {
602
- beginRoot = beginRoot || this.root;
603
- if (!beginRoot) return -1;
604
-
605
- if (this._loopType === LoopType.recursive) {
606
- const _getMinHeight = (cur: BinaryTreeNode<T> | null | undefined): number => {
607
- if (!cur) return 0;
608
- if (!cur.left && !cur.right) return 0;
609
- const leftMinHeight = _getMinHeight(cur.left);
610
- const rightMinHeight = _getMinHeight(cur.right);
611
- return Math.min(leftMinHeight, rightMinHeight) + 1;
612
- };
613
-
614
- return _getMinHeight(beginRoot);
615
- } else {
616
- const stack: BinaryTreeNode<T>[] = [];
617
- let node: BinaryTreeNode<T> | null | undefined = beginRoot, last: BinaryTreeNode<T> | null = null;
618
- const depths: Map<BinaryTreeNode<T>, number> = new Map();
619
-
620
- while (stack.length > 0 || node) {
621
- if (node) {
622
- stack.push(node);
623
- node = node.left;
624
- } else {
625
- node = stack[stack.length - 1]
626
- if (!node.right || last === node.right) {
627
- node = stack.pop();
628
- if (node) {
629
- const leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;
630
- const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1;
631
- depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
632
- last = node;
633
- node = null;
634
- }
635
- } else node = node.right
636
- }
637
- }
638
-
639
- return depths.get(beginRoot) ?? -1;
640
- }
641
- }
642
-
643
- /**
644
- * The function checks if a binary tree is balanced by comparing the minimum height and the maximum height of the tree.
645
- * @param {BinaryTreeNode<T> | null} [beginRoot] - The `beginRoot` parameter is the root node of a binary tree. It is
646
- * of type `BinaryTreeNode<T> | null`, which means it can either be a `BinaryTreeNode` object or `null`.
647
- * @returns The method is returning a boolean value.
648
- */
649
- isBalanced(beginRoot?: BinaryTreeNode<T> | null): boolean {
650
- return (this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot));
651
- }
652
-
653
- /**
654
- * The function `getNodes` returns an array of binary tree nodes that match a given property value, with options for
655
- * searching recursively or iteratively.
656
- * @param {BinaryTreeNodeId | T} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
657
- * generic type `T`. It represents the property of the binary tree node that you want to search for.
658
- * @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
659
- * specifies the property name to use when searching for nodes. If not provided, it defaults to 'id'.
660
- * @param {boolean} [onlyOne] - The `onlyOne` parameter is an optional boolean parameter that determines whether to
661
- * return only one node that matches the `nodeProperty` or `propertyName` criteria. If `onlyOne` is set to `true`, the
662
- * function will stop traversing the tree and return the first matching node. If `
663
- * @returns The function `getNodes` returns an array of `BinaryTreeNode<T> | null | undefined` objects.
664
- */
665
- getNodes(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean) {
666
- if (!this.root) return [] as null[];
667
- propertyName = propertyName ?? 'id';
668
-
669
- const result: (BinaryTreeNode<T> | null | undefined)[] = [];
670
-
671
- if (this._loopType === LoopType.recursive) {
672
- const _traverse = (cur: BinaryTreeNode<T>) => {
673
- if (this._pushByPropertyNameStopOrNot(cur, result, nodeProperty, propertyName, onlyOne)) return;
674
- if (!cur.left && !cur.right) return;
675
- cur.left && _traverse(cur.left);
676
- cur.right && _traverse(cur.right);
677
- }
678
-
679
- _traverse(this.root);
680
- } else {
681
- const queue: BinaryTreeNode<T>[] = [this.root];
682
- while (queue.length > 0) {
683
- const cur = queue.shift();
684
- if (cur) {
685
- if (this._pushByPropertyNameStopOrNot(cur, result, nodeProperty, propertyName, onlyOne)) return result;
686
- cur.left && queue.push(cur.left);
687
- cur.right && queue.push(cur.right);
688
- }
689
- }
690
- }
691
-
692
- return result;
693
- }
694
-
695
- /**
696
- * The function checks if a binary tree node has a specific property or if any node in the tree has a specific
697
- * property.
698
- * @param {BinaryTreeNodeId | T} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
699
- * generic type `T`. It represents the property of a binary tree node that you want to check.
700
- * @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
701
- * specifies the name of the property to check for in the nodes.
702
- * @returns a boolean value.
703
- */
704
- has(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName): boolean {
705
- return this.getNodes(nodeProperty, propertyName).length > 0;
706
- }
707
-
708
- /**
709
- * The function returns the first binary tree node that matches the given property name and value, or null if no match
710
- * is found.
711
- * @param {BinaryTreeNodeId | T} nodeProperty - The `nodeProperty` parameter can be either a `BinaryTreeNodeId` or a
712
- * generic type `T`. It represents the property of the binary tree node that you want to search for.
713
- * @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
714
- * specifies the property of the binary tree node to search for. If not provided, it defaults to `'id'`.
715
- * @returns a BinaryTreeNode object or null.
716
- */
717
- get(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName): BinaryTreeNode<T> | null {
718
- propertyName = propertyName ?? 'id';
719
- return this.getNodes(nodeProperty, propertyName, true)[0] ?? null;
720
- }
721
-
722
- /**
723
- * The function getPathToRoot returns an array of BinaryTreeNode objects representing the path from a given node to the
724
- * root of a binary tree.
725
- * @param node - The `node` parameter is a BinaryTreeNode object.
726
- * @returns The function `getPathToRoot` returns an array of `BinaryTreeNode<T>` objects, representing the path from
727
- * the given `node` to the root of the binary tree.
728
- */
729
- getPathToRoot(node: BinaryTreeNode<T>): BinaryTreeNode<T>[] {
730
- const result: BinaryTreeNode<T>[] = [];
731
- while (node.parent) {
732
- result.unshift(node);
733
- node = node.parent;
734
- }
735
- result.unshift(node);
736
- return result;
737
- }
738
-
739
- getLeftMost(): BinaryTreeNode<T> | null;
740
-
741
- getLeftMost(node: BinaryTreeNode<T>): BinaryTreeNode<T>;
742
-
743
- /**
744
- * The `getLeftMost` function returns the leftmost node in a binary tree, either recursively or iteratively using tail
745
- * recursion optimization.
746
- * @param {BinaryTreeNode<T> | null} [node] - The `node` parameter is an optional parameter of type `BinaryTreeNode<T>
747
- * | null`. It represents the starting node from which to find the leftmost node in a binary tree. If no node is
748
- * provided, the function will use the root node of the binary tree.
749
- * @returns The `getLeftMost` function returns the leftmost node in a binary tree.
750
- */
751
- getLeftMost(node?: BinaryTreeNode<T> | null): BinaryTreeNode<T> | null {
752
- node = node ?? this.root;
753
- if (!node) return node;
754
-
755
- if (this._loopType === LoopType.recursive) {
756
-
757
- const _traverse = (cur: BinaryTreeNode<T>): BinaryTreeNode<T> => {
758
- if (!cur.left) return cur;
759
- return _traverse(cur.left);
760
- }
761
-
762
- return _traverse(node);
763
- } else {
764
- // Indirect implementation of iteration using tail recursion optimization
765
- const _traverse = trampoline((cur: BinaryTreeNode<T>) => {
766
- if (!cur.left) return cur;
767
- return _traverse.cont(cur.left);
768
- });
769
-
770
- return _traverse(node);
771
- }
772
- }
773
-
774
- getRightMost(): BinaryTreeNode<T> | null;
775
-
776
- getRightMost(node: BinaryTreeNode<T>): BinaryTreeNode<T>;
777
-
778
- /**
779
- * The `getRightMost` function returns the rightmost node in a binary tree, either recursively or iteratively using
780
- * tail recursion optimization.
781
- * @param {BinaryTreeNode<T> | null} [node] - The `node` parameter is an optional parameter of type `BinaryTreeNode<T>
782
- * | null`. It represents the starting node from which to find the rightmost node in a binary tree. If no node is
783
- * provided, the function will use the root node of the binary tree.
784
- * @returns The `getRightMost` function returns the rightmost node in a binary tree.
785
- */
786
- getRightMost(node?: BinaryTreeNode<T> | null): BinaryTreeNode<T> | null {
787
- node = node ?? this.root;
788
- if (!node) return node;
789
-
790
- if (this._loopType === LoopType.recursive) {
791
- const _traverse = (cur: BinaryTreeNode<T>): BinaryTreeNode<T> => {
792
- if (!cur.right) return cur;
793
- return _traverse(cur.right);
794
- }
795
-
796
- return _traverse(node);
797
- } else {
798
- // Indirect implementation of iteration using tail recursion optimization
799
- const _traverse = trampoline((cur: BinaryTreeNode<T>) => {
800
- if (!cur.right) return cur;
801
- return _traverse.cont(cur.right);
802
- });
803
-
804
- return _traverse(node);
805
- }
806
- }
807
-
808
- // --- start additional methods ---
809
-
810
- /**
811
- * The `isBST` function checks if a binary tree is a binary search tree.
812
- * @param {BinaryTreeNode<T> | null} [node] - The `node` parameter is an optional parameter of type `BinaryTreeNode<T>
813
- * | null`. It represents the root node of the binary search tree (BST) that we want to check for validity. If no node
814
- * is provided, the function will default to using the root node of the BST instance that
815
- * @returns The `isBST` function returns a boolean value. It returns `true` if the binary tree is a valid binary search
816
- * tree, and `false` otherwise.
817
- */
818
- isBST(node?: BinaryTreeNode<T> | null): boolean {
819
- node = node ?? this.root;
820
- if (!node) return true;
821
-
822
- if (this._loopType === LoopType.recursive) {
823
- const dfs = (cur: BinaryTreeNode<T> | null | undefined, min: BinaryTreeNodeId, max: BinaryTreeNodeId): boolean => {
824
- if (!cur) return true;
825
- if (cur.id <= min || cur.id >= max) return false;
826
- return dfs(cur.left, min, cur.id) && dfs(cur.right, cur.id, max);
827
- }
828
-
829
- return dfs(node, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
830
- } else {
831
- const stack = [];
832
- let prev = Number.MIN_SAFE_INTEGER, curr: BinaryTreeNode<T> | null | undefined = node;
833
- while (curr || stack.length > 0) {
834
- while (curr) {
835
- stack.push(curr);
836
- curr = curr.left;
837
- }
838
- curr = stack.pop()!;
839
- if (!(curr) || prev >= curr.id) return false;
840
- prev = curr.id;
841
- curr = curr.right;
842
- }
843
- return true;
844
- }
845
- }
846
-
847
- /**
848
- * The function calculates the size and count of a subtree in a binary tree using either recursive or iterative
849
- * traversal.
850
- * @param {BinaryTreeNode<T> | null | undefined} subTreeRoot - The `subTreeRoot` parameter is the root node of a binary
851
- * tree.
852
- * @returns The function `getSubTreeSizeAndCount` returns an array `[number, number]`. The first element of the array
853
- * represents the size of the subtree, and the second element represents the count of the nodes in the subtree.
854
- */
855
- getSubTreeSizeAndCount(subTreeRoot: BinaryTreeNode<T> | null | undefined) {
856
- const res: [number, number] = [0, 0];
857
- if (!subTreeRoot) return res;
858
-
859
- if (this._loopType === LoopType.recursive) {
860
- const _traverse = (cur: BinaryTreeNode<T>) => {
861
- res[0]++;
862
- res[1] += cur.count;
863
- cur.left && _traverse(cur.left);
864
- cur.right && _traverse(cur.right);
865
- }
866
-
867
- _traverse(subTreeRoot);
868
- return res;
869
- } else {
870
- const stack: BinaryTreeNode<T>[] = [subTreeRoot];
871
-
872
- while (stack.length > 0) {
873
- const cur = stack.pop()!;
874
- res[0]++;
875
- res[1] += cur.count;
876
- cur.right && stack.push(cur.right);
877
- cur.left && stack.push(cur.left);
878
- }
879
-
880
- return res;
881
- }
882
- }
883
-
884
- /**
885
- * The function `subTreeSum` calculates the sum of a specified property in a binary tree, either recursively or
886
- * iteratively.
887
- * @param subTreeRoot - The subTreeRoot parameter is the root node of the subtree for which you want to calculate the
888
- * sum.
889
- * @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
890
- * specifies the property of the `BinaryTreeNode` object to use for calculating the sum. If `propertyName` is not
891
- * provided, it defaults to `'val'`.
892
- * @returns a number, which is the sum of the values of the nodes in the subtree rooted at `subTreeRoot`.
893
- */
894
- subTreeSum(subTreeRoot: BinaryTreeNode<T>, propertyName ?: BinaryTreeNodePropertyName): number {
895
- propertyName = propertyName ?? 'val';
896
- if (!subTreeRoot) return 0;
897
-
898
- let sum = 0;
899
-
900
- const _sumByProperty = (cur: BinaryTreeNode<T>) => {
901
- let needSum: number;
902
- switch (propertyName) {
903
- case 'id':
904
- needSum = cur.id;
905
- break;
906
- case 'count':
907
- needSum = cur.count;
908
- break;
909
- case 'val':
910
- needSum = typeof cur.val === 'number' ? cur.val : 0;
911
- break;
912
- default:
913
- needSum = cur.id;
914
- break;
915
- }
916
- return needSum;
917
- }
918
-
919
- if (this._loopType === LoopType.recursive) {
920
- const _traverse = (cur: BinaryTreeNode<T>): void => {
921
- sum += _sumByProperty(cur);
922
- cur.left && _traverse(cur.left);
923
- cur.right && _traverse(cur.right);
924
- }
925
-
926
- _traverse(subTreeRoot);
927
- } else {
928
- const stack: BinaryTreeNode<T>[] = [subTreeRoot];
929
-
930
- while (stack.length > 0) {
931
- const cur = stack.pop()!;
932
- sum += _sumByProperty(cur);
933
- cur.right && stack.push(cur.right);
934
- cur.left && stack.push(cur.left);
935
- }
936
- }
937
-
938
- return sum;
939
- }
940
-
941
- /**
942
- * The function `subTreeAdd` adds a specified delta value to a property of each node in a binary tree.
943
- * @param subTreeRoot - The `subTreeRoot` parameter is the root node of the subtree where the values will be modified.
944
- * @param {number} delta - The `delta` parameter is a number that represents the amount by which the property value of
945
- * each node in the subtree should be increased or decreased.
946
- * @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
947
- * specifies the property of the `BinaryTreeNode` that should be modified. It defaults to `'id'` if not provided.
948
- * @returns a boolean value, which is `true`.
949
- */
950
- subTreeAdd(subTreeRoot: BinaryTreeNode<T>, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean {
951
- propertyName = propertyName ?? 'id';
952
- if (!subTreeRoot) return false;
953
-
954
- const _addByProperty = (cur: BinaryTreeNode<T>) => {
955
- switch (propertyName) {
956
- case 'id':
957
- cur.id += delta;
958
- break;
959
- case 'count':
960
- cur.count += delta;
961
- this.count += delta;
962
- break;
963
- default:
964
- cur.id += delta;
965
- break;
966
- }
967
- }
968
-
969
- if (this._loopType === LoopType.recursive) {
970
- const _traverse = (cur: BinaryTreeNode<T>) => {
971
- _addByProperty(cur);
972
- cur.left && _traverse(cur.left);
973
- cur.right && _traverse(cur.right);
974
- };
975
-
976
- _traverse(subTreeRoot);
977
- } else {
978
- const stack: BinaryTreeNode<T>[] = [subTreeRoot];
979
-
980
- while (stack.length > 0) {
981
- const cur = stack.pop()!;
982
-
983
- _addByProperty(cur);
984
- cur.right && stack.push(cur.right);
985
- cur.left && stack.push(cur.left);
986
- }
987
- }
988
- return true;
989
- }
990
-
991
- BFS(): BinaryTreeNodeId[];
992
-
993
- BFS(nodeOrPropertyName: 'id'): BinaryTreeNodeId[];
994
-
995
- BFS(nodeOrPropertyName: 'val'): T[];
996
-
997
- BFS(nodeOrPropertyName: 'node'): BinaryTreeNode<T>[];
998
-
999
- BFS(nodeOrPropertyName: 'count'): number[];
1000
-
1001
- /**
1002
- * The BFS function performs a breadth-first search on a binary tree and returns the results based on a specified node
1003
- * or property name.
1004
- * @param {NodeOrPropertyName} [nodeOrPropertyName] - The parameter `nodeOrPropertyName` is an optional parameter that
1005
- * represents either a node or a property name. If a node is provided, the breadth-first search algorithm will be
1006
- * performed starting from that node. If a property name is provided, the breadth-first search algorithm will be
1007
- * performed starting from the root node
1008
- * @returns an object of type `ResultsByProperty<T>`.
1009
- */
1010
- BFS(nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty<T> {
1011
- nodeOrPropertyName = nodeOrPropertyName ?? 'id';
1012
- this._resetResults();
1013
- const queue: Array<BinaryTreeNode<T> | null | undefined> = [this.root];
1014
-
1015
- while (queue.length !== 0) {
1016
- const cur = queue.shift();
1017
- if (cur) {
1018
- this._accumulatedByPropertyName(cur, nodeOrPropertyName);
1019
- if (cur?.left !== null) queue.push(cur.left);
1020
- if (cur?.right !== null) queue.push(cur.right);
1021
- }
1022
- }
1023
-
1024
- return this._getResultByPropertyName(nodeOrPropertyName);
1025
- }
1026
-
1027
- DFS(): BinaryTreeNodeId[];
1028
-
1029
- DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
1030
-
1031
- DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'val'): T[];
1032
-
1033
- DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'node'): BinaryTreeNode<T>[];
1034
-
1035
- DFS(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
1036
-
1037
- /**
1038
- * The DFS function performs a depth-first search traversal on a binary tree and returns the results based on the
1039
- * specified pattern and node or property name.
1040
- * @param {'in' | 'pre' | 'post'} [pattern] - The "pattern" parameter is used to specify the order in which the nodes
1041
- * of a binary tree are traversed during the Depth-First Search (DFS) algorithm. It can take one of three values: 'in',
1042
- * 'pre', or 'post'.
1043
- * @param {NodeOrPropertyName} [nodeOrPropertyName] - The `nodeOrPropertyName` parameter is a string that represents
1044
- * either the name of a property in the `BinaryTreeNode` object or the value of the `id` property in the
1045
- * `BinaryTreeNode` object. This parameter is used to accumulate the results based on the specified property name. If
1046
- * no value
1047
- * @returns an object of type `ResultsByProperty<T>`.
1048
- */
1049
- DFS(pattern ?: 'in' | 'pre' | 'post', nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty<T> {
1050
- pattern = pattern ?? 'in';
1051
- nodeOrPropertyName = nodeOrPropertyName ?? 'id';
1052
- this._resetResults();
1053
- const _traverse = (node: BinaryTreeNode<T>) => {
1054
- switch (pattern) {
1055
- case 'in':
1056
- if (node.left) _traverse(node.left);
1057
- this._accumulatedByPropertyName(node, nodeOrPropertyName);
1058
- if (node.right) _traverse(node.right);
1059
- break;
1060
- case 'pre':
1061
- this._accumulatedByPropertyName(node, nodeOrPropertyName);
1062
- if (node.left) _traverse(node.left);
1063
- if (node.right) _traverse(node.right);
1064
- break;
1065
- case 'post':
1066
- if (node.left) _traverse(node.left);
1067
- if (node.right) _traverse(node.right);
1068
- this._accumulatedByPropertyName(node, nodeOrPropertyName);
1069
- break;
1070
- }
1071
- };
1072
-
1073
- this.root && _traverse(this.root);
1074
- return this._getResultByPropertyName(nodeOrPropertyName);
1075
- }
1076
-
1077
- DFSIterative(): BinaryTreeNodeId[];
1078
-
1079
- DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
1080
-
1081
- DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'val'): T[];
1082
-
1083
- DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'node'): BinaryTreeNode<T>[];
1084
-
1085
- DFSIterative(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
1086
-
1087
- /**
1088
- * Time complexity is O(n)
1089
- * Space complexity of Iterative DFS equals to recursive DFS which is O(n) because of the stack
1090
- * @param pattern
1091
- * @param nodeOrPropertyName
1092
- * @constructor
1093
- */
1094
- DFSIterative(pattern ?: 'in' | 'pre' | 'post', nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty<T> {
1095
- pattern = pattern || 'in';
1096
- nodeOrPropertyName = nodeOrPropertyName || 'id';
1097
- this._resetResults();
1098
- if (!this.root) return this._getResultByPropertyName(nodeOrPropertyName);
1099
- // 0: visit, 1: print
1100
- const stack: { opt: 0 | 1, node: BinaryTreeNode<T> | null | undefined }[] = [{opt: 0, node: this.root}];
1101
-
1102
- while (stack.length > 0) {
1103
- const cur = stack.pop();
1104
- if (!cur || !cur.node) continue;
1105
- if (cur.opt === 1) {
1106
- this._accumulatedByPropertyName(cur.node, nodeOrPropertyName);
1107
- } else {
1108
- switch (pattern) {
1109
- case 'in':
1110
- stack.push({opt: 0, node: cur.node.right});
1111
- stack.push({opt: 1, node: cur.node});
1112
- stack.push({opt: 0, node: cur.node.left});
1113
- break;
1114
- case 'pre':
1115
- stack.push({opt: 0, node: cur.node.right});
1116
- stack.push({opt: 0, node: cur.node.left});
1117
- stack.push({opt: 1, node: cur.node});
1118
- break;
1119
- case 'post':
1120
- stack.push({opt: 1, node: cur.node});
1121
- stack.push({opt: 0, node: cur.node.right});
1122
- stack.push({opt: 0, node: cur.node.left});
1123
- break;
1124
- default:
1125
- stack.push({opt: 0, node: cur.node.right});
1126
- stack.push({opt: 1, node: cur.node});
1127
- stack.push({opt: 0, node: cur.node.left});
1128
- break;
1129
- }
1130
- }
1131
- }
1132
-
1133
- return this._getResultByPropertyName(nodeOrPropertyName);
1134
- }
1135
-
1136
- levelIterative(node: BinaryTreeNode<T> | null): BinaryTreeNodeId[];
1137
-
1138
- levelIterative(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
1139
-
1140
- levelIterative(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'val'): T[];
1141
-
1142
- levelIterative(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'node'): BinaryTreeNode<T>[];
1143
-
1144
- levelIterative(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'count'): number[];
1145
-
1146
- /**
1147
- * The `levelIterative` function performs a level-order traversal on a binary tree and returns the values of the nodes
1148
- * in an array, based on a specified property name.
1149
- * @param {BinaryTreeNode<T> | null} node - The `node` parameter is a BinaryTreeNode object representing the starting
1150
- * node for the level order traversal. It can be null if no specific node is provided, in which case the root node of
1151
- * the tree is used as the starting node.
1152
- * @param {NodeOrPropertyName} [nodeOrPropertyName] - The `nodeOrPropertyName` parameter is an optional parameter that
1153
- * can be either a `BinaryTreeNode` property name or the string `'id'`. If a property name is provided, the function
1154
- * will accumulate results based on that property. If no property name is provided, the function will default to
1155
- * accumulating results
1156
- * @returns The function `levelIterative` returns an object of type `ResultsByProperty<T>`.
1157
- */
1158
- levelIterative(node: BinaryTreeNode<T> | null, nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty<T> {
1159
- nodeOrPropertyName = nodeOrPropertyName || 'id';
1160
- node = node || this.root;
1161
- if (!node) return [];
1162
-
1163
- this._resetResults();
1164
- const queue: BinaryTreeNode<T>[] = [node];
1165
-
1166
- while (queue.length > 0) {
1167
- const cur = queue.shift();
1168
- if (cur) {
1169
- this._accumulatedByPropertyName(cur, nodeOrPropertyName);
1170
- if (cur.left) {
1171
- queue.push(cur.left);
1172
- }
1173
- if (cur.right) {
1174
- queue.push(cur.right);
1175
- }
1176
- }
1177
- }
1178
-
1179
- return this._getResultByPropertyName(nodeOrPropertyName);
1180
- }
1181
-
1182
- listLevels(node: BinaryTreeNode<T> | null): BinaryTreeNodeId[][];
1183
-
1184
- listLevels(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[][];
1185
-
1186
- listLevels(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'val'): T[][];
1187
-
1188
- listLevels(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'node'): BinaryTreeNode<T>[][];
1189
-
1190
- listLevels(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: 'count'): number[][];
1191
-
1192
- /**
1193
- * The `listLevels` function collects nodes from a binary tree by a specified property and organizes them into levels.
1194
- * @param {BinaryTreeNode<T> | null} node - The `node` parameter is a BinaryTreeNode object or null. It represents the
1195
- * root node of a binary tree. If it is null, the function will use the root node of the current binary tree instance.
1196
- * @param {NodeOrPropertyName} [nodeOrPropertyName] - The `nodeOrPropertyName` parameter is an optional parameter that
1197
- * specifies the property of the `BinaryTreeNode` object to collect at each level. It can be one of the following
1198
- * values:
1199
- * @returns The function `listLevels` returns a 2D array of `ResultByProperty<T>` objects.
1200
- */
1201
- listLevels(node: BinaryTreeNode<T> | null, nodeOrPropertyName?: NodeOrPropertyName): ResultByProperty<T>[][] {
1202
- nodeOrPropertyName = nodeOrPropertyName || 'id';
1203
- node = node || this.root;
1204
- if (!node) return [];
1205
-
1206
- const levelsNodes: ResultByProperty<T>[][] = [];
1207
-
1208
- const collectByProperty = (node: BinaryTreeNode<T>, level: number) => {
1209
- switch (nodeOrPropertyName) {
1210
- case 'id':
1211
- levelsNodes[level].push(node.id);
1212
- break;
1213
- case 'val':
1214
- levelsNodes[level].push(node.val);
1215
- break;
1216
- case 'node':
1217
- levelsNodes[level].push(node);
1218
- break;
1219
- case 'count':
1220
- levelsNodes[level].push(node.count);
1221
- break;
1222
- default:
1223
- levelsNodes[level].push(node.id);
1224
- break;
1225
- }
1226
- }
1227
-
1228
- if (this._loopType === LoopType.recursive) {
1229
- const _recursive = (node: BinaryTreeNode<T>, level: number) => {
1230
- if (!levelsNodes[level]) levelsNodes[level] = [];
1231
- collectByProperty(node, level);
1232
- if (node.left) _recursive(node.left, level + 1);
1233
- if (node.right) _recursive(node.right, level + 1);
1234
- };
1235
-
1236
- _recursive(node, 0);
1237
- } else {
1238
- const stack: [BinaryTreeNode<T>, number][] = [[node, 0]];
1239
-
1240
- while (stack.length > 0) {
1241
- const head = stack.pop()!;
1242
- const [node, level] = head;
1243
-
1244
- if (!levelsNodes[level]) levelsNodes[level] = [];
1245
- collectByProperty(node, level);
1246
- if (node.right) stack.push([node.right, level + 1]);
1247
- if (node.left) stack.push([node.left, level + 1]);
1248
- }
1249
- }
1250
-
1251
- return levelsNodes;
1252
- }
1253
-
1254
- /**
1255
- * The function returns the predecessor of a given node in a binary tree.
1256
- * @param node - The parameter `node` is a BinaryTreeNode object, representing a node in a binary tree.
1257
- * @returns the predecessor of the given node in a binary tree.
1258
- */
1259
- getPredecessor(node: BinaryTreeNode<T>): BinaryTreeNode<T> {
1260
- if (node.left) {
1261
- let predecessor: BinaryTreeNode<T> | null | undefined = node.left;
1262
- while (!(predecessor) || predecessor.right && predecessor.right !== node) {
1263
- if (predecessor) {
1264
- predecessor = predecessor.right;
1265
- }
1266
- }
1267
- return predecessor;
1268
- } else {
1269
- return node;
1270
- }
1271
- }
1272
-
1273
- morris(): BinaryTreeNodeId[];
1274
-
1275
- morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'id'): BinaryTreeNodeId[];
1276
-
1277
- morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'val'): T[];
1278
-
1279
- morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'node'): BinaryTreeNode<T>[];
1280
-
1281
- morris(pattern?: DFSOrderPattern, nodeOrPropertyName?: 'count'): number[];
1282
-
1283
- /**
1284
- * The `morris` function performs an in-order, pre-order, or post-order traversal on a binary tree using the Morris
1285
- * traversal algorithm and returns the results based on the specified property name.
1286
- * The time complexity of Morris traversal is O(n), it's may slower than others
1287
- * The space complexity Morris traversal is O(1) because no using stack
1288
- * @param {'in' | 'pre' | 'post'} [pattern] - The `pattern` parameter is an optional parameter that determines the
1289
- * traversal pattern of the binary tree. It can have one of three values:
1290
- * @param {NodeOrPropertyName} [nodeOrPropertyName] - The `nodeOrPropertyName` parameter is used to specify the
1291
- * property of the nodes that you want to retrieve in the results. It can be either the node itself or the name of the
1292
- * property. If not provided, it defaults to `'id'`.
1293
- * @returns The function `morris` returns an object of type `ResultsByProperty<T>`.
1294
- */
1295
- morris(pattern?: 'in' | 'pre' | 'post', nodeOrPropertyName?: NodeOrPropertyName): ResultsByProperty<T> {
1296
- if (this.root === null) return [];
1297
-
1298
- pattern = pattern || 'in';
1299
- nodeOrPropertyName = nodeOrPropertyName || 'id';
1300
-
1301
- this._resetResults();
1302
-
1303
- let cur: BinaryTreeNode<T> | null | undefined = this.root;
1304
- const _reverseEdge = (node: BinaryTreeNode<T> | null | undefined) => {
1305
- let pre: BinaryTreeNode<T> | null | undefined = null;
1306
- let next: BinaryTreeNode<T> | null | undefined = null;
1307
- while (node) {
1308
- next = node.right;
1309
- node.right = pre;
1310
- pre = node;
1311
- node = next;
1312
- }
1313
- return pre;
1314
- };
1315
- const _printEdge = (node: BinaryTreeNode<T> | null) => {
1316
- const tail: BinaryTreeNode<T> | null | undefined = _reverseEdge(node);
1317
- let cur: BinaryTreeNode<T> | null | undefined = tail;
1318
- while (cur) {
1319
- this._accumulatedByPropertyName(cur, nodeOrPropertyName);
1320
- cur = cur.right;
1321
- }
1322
- _reverseEdge(tail);
1323
- };
1324
- switch (pattern) {
1325
- case 'in':
1326
- while (cur) {
1327
- if (cur.left) {
1328
- const predecessor = this.getPredecessor(cur);
1329
- if (!predecessor.right) {
1330
- predecessor.right = cur;
1331
- cur = cur.left;
1332
- continue;
1333
- } else {
1334
- predecessor.right = null;
1335
- }
1336
- }
1337
- this._accumulatedByPropertyName(cur, nodeOrPropertyName);
1338
- cur = cur.right;
1339
- }
1340
- break;
1341
- case 'pre':
1342
- while (cur) {
1343
- if (cur.left) {
1344
- const predecessor = this.getPredecessor(cur);
1345
- if (!predecessor.right) {
1346
- predecessor.right = cur;
1347
- this._accumulatedByPropertyName(cur, nodeOrPropertyName);
1348
- cur = cur.left;
1349
- continue;
1350
- } else {
1351
- predecessor.right = null;
1352
- }
1353
- } else {
1354
- this._accumulatedByPropertyName(cur, nodeOrPropertyName);
1355
- }
1356
- cur = cur.right;
1357
- }
1358
- break;
1359
- case 'post':
1360
- while (cur) {
1361
- if (cur.left) {
1362
- const predecessor = this.getPredecessor(cur);
1363
- if (predecessor.right === null) {
1364
- predecessor.right = cur;
1365
- cur = cur.left;
1366
- continue;
1367
- } else {
1368
- predecessor.right = null;
1369
- _printEdge(cur.left);
1370
- }
1371
- }
1372
- cur = cur.right;
1373
- }
1374
- _printEdge(this.root);
1375
- break;
1376
- }
1377
-
1378
- return this._getResultByPropertyName(nodeOrPropertyName);
1379
- }
1380
-
1381
- /**
1382
- * The function resets the values of several arrays used for tracking visited nodes and their properties.
1383
- */
1384
- protected _resetResults() {
1385
- this._visitedId = [];
1386
- this._visitedVal = [];
1387
- this._visitedNode = [];
1388
- this._visitedCount = [];
1389
- this._visitedLeftSum = [];
1390
- }
1391
-
1392
- /**
1393
- * The function checks if a given property of a binary tree node matches a specified value, and if so, adds the node to
1394
- * a result array.
1395
- * @param cur - The current binary tree node that is being checked.
1396
- * @param {(BinaryTreeNode<T> | null | undefined)[]} result - An array that stores the matching nodes found during the
1397
- * traversal.
1398
- * @param {BinaryTreeNodeId | T} nodeProperty - The `nodeProperty` parameter is the value that we are searching for in
1399
- * the binary tree nodes. It can be either the `id`, `count`, or `val` property of the node.
1400
- * @param {BinaryTreeNodePropertyName} [propertyName] - The `propertyName` parameter is an optional parameter that
1401
- * specifies the property of the `BinaryTreeNode` object that you want to compare with the `nodeProperty` value. It can
1402
- * be one of the following values: 'id', 'count', or 'val'. If no `propertyName` is provided,
1403
- * @param {boolean} [onlyOne] - The `onlyOne` parameter is an optional boolean parameter that determines whether to
1404
- * stop after finding the first matching node or continue searching for all matching nodes. If `onlyOne` is set to
1405
- * `true`, the function will stop after finding the first matching node and return `true`. If `onlyOne
1406
- * @returns a boolean value indicating whether or not a node was pushed into the result array.
1407
- */
1408
- protected _pushByPropertyNameStopOrNot(cur: BinaryTreeNode<T>, result: (BinaryTreeNode<T> | null | undefined)[], nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean) {
1409
- switch (propertyName) {
1410
- case 'id':
1411
- if (cur.id === nodeProperty) {
1412
- result.push(cur);
1413
- return !!onlyOne;
1414
- }
1415
- break;
1416
- case 'count':
1417
- if (cur.count === nodeProperty) {
1418
- result.push(cur);
1419
- return !!onlyOne;
1420
- }
1421
- break;
1422
- case 'val':
1423
- if (cur.val === nodeProperty) {
1424
- result.push(cur);
1425
- return !!onlyOne;
1426
- }
1427
- break;
1428
- default:
1429
- if (cur.id === nodeProperty) {
1430
- result.push(cur);
1431
- return !!onlyOne;
1432
- }
1433
- break;
1434
- }
1435
- }
1436
-
1437
- /**
1438
- * The function `_accumulatedByPropertyName` pushes a property value of a binary tree node into an array based on the
1439
- * provided property name or a default property name.
1440
- * @param node - The `node` parameter is of type `BinaryTreeNode<T>`, which represents a node in a binary tree.
1441
- * @param {NodeOrPropertyName} [nodeOrPropertyName] - The parameter `nodeOrPropertyName` is an optional parameter that
1442
- * can be either a string representing a property name or a reference to a node object. If it is a string, it specifies
1443
- * the property name of the node that should be accumulated. If it is a node object, it specifies the node itself
1444
- */
1445
- protected _accumulatedByPropertyName(node: BinaryTreeNode<T>, nodeOrPropertyName ?: NodeOrPropertyName) {
1446
- nodeOrPropertyName = nodeOrPropertyName ?? 'id';
1447
-
1448
- switch (nodeOrPropertyName) {
1449
- case 'id':
1450
- this._visitedId.push(node.id);
1451
- break;
1452
- case 'val':
1453
- this._visitedVal.push(node.val);
1454
- break;
1455
- case 'node':
1456
- this._visitedNode.push(node);
1457
- break;
1458
- case 'count':
1459
- this._visitedCount.push(node.count);
1460
- break;
1461
- default:
1462
- this._visitedId.push(node.id);
1463
- break;
1464
- }
1465
- }
1466
-
1467
- /**
1468
- * The function `_getResultByPropertyName` returns different results based on the provided property name or defaulting
1469
- * to 'id'.
1470
- * @param {NodeOrPropertyName} [nodeOrPropertyName] - The parameter `nodeOrPropertyName` is an optional parameter that
1471
- * can accept a value of type `NodeOrPropertyName`.
1472
- * @returns The method returns an object of type `ResultsByProperty<T>`.
1473
- */
1474
- protected _getResultByPropertyName(nodeOrPropertyName ?: NodeOrPropertyName): ResultsByProperty<T> {
1475
- nodeOrPropertyName = nodeOrPropertyName ?? 'id';
1476
-
1477
- switch (nodeOrPropertyName) {
1478
- case 'id':
1479
- return this._visitedId;
1480
- case 'val':
1481
- return this._visitedVal;
1482
- case 'node':
1483
- return this._visitedNode;
1484
- case 'count':
1485
- return this._visitedCount;
1486
- default:
1487
- return this._visitedId;
1488
- }
1489
- }
1490
-
1491
- // --- end additional methods ---
1492
- }