@gabrielrufino/cube 1.0.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.
Files changed (240) hide show
  1. package/.github/workflows/cd.yml +26 -0
  2. package/.github/workflows/ci.yml +23 -0
  3. package/LICENSE +24 -0
  4. package/README.md +1695 -0
  5. package/build/Algorithms/index.d.ts +3 -0
  6. package/build/Algorithms/index.js +24 -0
  7. package/build/Array/IArray.d.ts +9 -0
  8. package/build/Array/IArray.js +2 -0
  9. package/build/Array/index.d.ts +12 -0
  10. package/build/Array/index.js +79 -0
  11. package/build/BinarySearchTree/BinarySearchTreeNode.d.ts +7 -0
  12. package/build/BinarySearchTree/BinarySearchTreeNode.js +22 -0
  13. package/build/BinarySearchTree/IBinarySearchNodeOptions.d.ts +5 -0
  14. package/build/BinarySearchTree/IBinarySearchNodeOptions.js +2 -0
  15. package/build/BinarySearchTree/IBinarySearchTree.d.ts +14 -0
  16. package/build/BinarySearchTree/IBinarySearchTree.js +2 -0
  17. package/build/BinarySearchTree/IBinarySearchTreeData.d.ts +7 -0
  18. package/build/BinarySearchTree/IBinarySearchTreeData.js +2 -0
  19. package/build/BinarySearchTree/index.d.ts +24 -0
  20. package/build/BinarySearchTree/index.js +199 -0
  21. package/build/DataStructure/index.d.ts +6 -0
  22. package/build/DataStructure/index.js +32 -0
  23. package/build/Deck/IDeck.d.ts +9 -0
  24. package/build/Deck/IDeck.js +2 -0
  25. package/build/Deck/index.d.ts +12 -0
  26. package/build/Deck/index.js +76 -0
  27. package/build/Dictionary/IDictionary.d.ts +16 -0
  28. package/build/Dictionary/IDictionary.js +2 -0
  29. package/build/Dictionary/IDictionaryData.d.ts +4 -0
  30. package/build/Dictionary/IDictionaryData.js +2 -0
  31. package/build/Dictionary/index.d.ts +21 -0
  32. package/build/Dictionary/index.js +110 -0
  33. package/build/DoublyLinkedList/IDoublyLinkedList.d.ts +16 -0
  34. package/build/DoublyLinkedList/IDoublyLinkedList.js +2 -0
  35. package/build/DoublyLinkedList/Node.d.ts +6 -0
  36. package/build/DoublyLinkedList/Node.js +11 -0
  37. package/build/DoublyLinkedList/index.d.ts +32 -0
  38. package/build/DoublyLinkedList/index.js +221 -0
  39. package/build/Graph/GraphNodeNotFoundError.d.ts +3 -0
  40. package/build/Graph/GraphNodeNotFoundError.js +27 -0
  41. package/build/Graph/GraphSearchNodeStates.d.ts +6 -0
  42. package/build/Graph/GraphSearchNodeStates.js +10 -0
  43. package/build/Graph/IGraph.d.ts +16 -0
  44. package/build/Graph/IGraph.js +2 -0
  45. package/build/Graph/IGraphOptions.d.ts +7 -0
  46. package/build/Graph/IGraphOptions.js +2 -0
  47. package/build/Graph/index.d.ts +20 -0
  48. package/build/Graph/index.js +187 -0
  49. package/build/HashTable/IHashTable.d.ts +9 -0
  50. package/build/HashTable/IHashTable.js +2 -0
  51. package/build/HashTable/IHashTableData.d.ts +4 -0
  52. package/build/HashTable/IHashTableData.js +2 -0
  53. package/build/HashTable/IHashTableInputs.d.ts +4 -0
  54. package/build/HashTable/IHashTableInputs.js +2 -0
  55. package/build/HashTable/IHashTableOptions.d.ts +4 -0
  56. package/build/HashTable/IHashTableOptions.js +2 -0
  57. package/build/HashTable/index.d.ts +16 -0
  58. package/build/HashTable/index.js +83 -0
  59. package/build/HashTableLinearProbing/HashTableLinearProbingElement.d.ts +6 -0
  60. package/build/HashTableLinearProbing/HashTableLinearProbingElement.js +19 -0
  61. package/build/HashTableLinearProbing/IHashTableLinearProbing.d.ts +9 -0
  62. package/build/HashTableLinearProbing/IHashTableLinearProbing.js +2 -0
  63. package/build/HashTableLinearProbing/IHashTableLinearProbingData.d.ts +5 -0
  64. package/build/HashTableLinearProbing/IHashTableLinearProbingData.js +2 -0
  65. package/build/HashTableLinearProbing/IHashTableLinearProbingInputs.d.ts +4 -0
  66. package/build/HashTableLinearProbing/IHashTableLinearProbingInputs.js +2 -0
  67. package/build/HashTableLinearProbing/IHashTableLinearProbingOptions.d.ts +4 -0
  68. package/build/HashTableLinearProbing/IHashTableLinearProbingOptions.js +2 -0
  69. package/build/HashTableLinearProbing/index.d.ts +20 -0
  70. package/build/HashTableLinearProbing/index.js +120 -0
  71. package/build/HashTableSeparateChaining/HashTableSeparateChainingElement.d.ts +6 -0
  72. package/build/HashTableSeparateChaining/HashTableSeparateChainingElement.js +21 -0
  73. package/build/HashTableSeparateChaining/IHashTableSeparateChaining.d.ts +10 -0
  74. package/build/HashTableSeparateChaining/IHashTableSeparateChaining.js +2 -0
  75. package/build/HashTableSeparateChaining/IHashTableSeparateChainingData.d.ts +5 -0
  76. package/build/HashTableSeparateChaining/IHashTableSeparateChainingData.js +2 -0
  77. package/build/HashTableSeparateChaining/IHashTableSeparateChainingInputs.d.ts +4 -0
  78. package/build/HashTableSeparateChaining/IHashTableSeparateChainingInputs.js +2 -0
  79. package/build/HashTableSeparateChaining/IHashTableSeparateChainingOptions.d.ts +4 -0
  80. package/build/HashTableSeparateChaining/IHashTableSeparateChainingOptions.js +2 -0
  81. package/build/HashTableSeparateChaining/index.d.ts +19 -0
  82. package/build/HashTableSeparateChaining/index.js +104 -0
  83. package/build/LinkedList/ILinkedList.d.ts +13 -0
  84. package/build/LinkedList/ILinkedList.js +2 -0
  85. package/build/LinkedList/ILinkedListItem.d.ts +5 -0
  86. package/build/LinkedList/ILinkedListItem.js +2 -0
  87. package/build/LinkedList/Node.d.ts +5 -0
  88. package/build/LinkedList/Node.js +10 -0
  89. package/build/LinkedList/index.d.ts +24 -0
  90. package/build/LinkedList/index.js +169 -0
  91. package/build/List/index.d.ts +1 -0
  92. package/build/List/index.js +8 -0
  93. package/build/MaxHeap/IMaxHeap.d.ts +9 -0
  94. package/build/MaxHeap/IMaxHeap.js +2 -0
  95. package/build/MaxHeap/IMaxHeapOptions.d.ts +5 -0
  96. package/build/MaxHeap/IMaxHeapOptions.js +2 -0
  97. package/build/MaxHeap/index.d.ts +19 -0
  98. package/build/MaxHeap/index.js +102 -0
  99. package/build/MinHeap/IMinHeap.d.ts +9 -0
  100. package/build/MinHeap/IMinHeap.js +2 -0
  101. package/build/MinHeap/IMinHeapOptions.d.ts +5 -0
  102. package/build/MinHeap/IMinHeapOptions.js +2 -0
  103. package/build/MinHeap/index.d.ts +19 -0
  104. package/build/MinHeap/index.js +102 -0
  105. package/build/Queue/IQueue.d.ts +8 -0
  106. package/build/Queue/IQueue.js +2 -0
  107. package/build/Queue/index.d.ts +11 -0
  108. package/build/Queue/index.js +74 -0
  109. package/build/Set/ISet.d.ts +15 -0
  110. package/build/Set/ISet.js +2 -0
  111. package/build/Set/index.d.ts +21 -0
  112. package/build/Set/index.js +132 -0
  113. package/build/Stack/IStack.d.ts +8 -0
  114. package/build/Stack/IStack.js +2 -0
  115. package/build/Stack/index.d.ts +11 -0
  116. package/build/Stack/index.js +64 -0
  117. package/build/index.d.ts +17 -0
  118. package/build/index.js +40 -0
  119. package/coverage/clover.xml +706 -0
  120. package/coverage/coverage-final.json +19 -0
  121. package/coverage/lcov-report/base.css +224 -0
  122. package/coverage/lcov-report/block-navigation.js +87 -0
  123. package/coverage/lcov-report/favicon.png +0 -0
  124. package/coverage/lcov-report/index.html +327 -0
  125. package/coverage/lcov-report/prettify.css +1 -0
  126. package/coverage/lcov-report/prettify.js +2 -0
  127. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  128. package/coverage/lcov-report/sorter.js +196 -0
  129. package/coverage/lcov-report/src/Algorithms/index.html +117 -0
  130. package/coverage/lcov-report/src/Algorithms/index.ts.html +149 -0
  131. package/coverage/lcov-report/src/Array/index.html +117 -0
  132. package/coverage/lcov-report/src/Array/index.ts.html +290 -0
  133. package/coverage/lcov-report/src/DataStructure/index.html +117 -0
  134. package/coverage/lcov-report/src/DataStructure/index.ts.html +131 -0
  135. package/coverage/lcov-report/src/Deck/index.html +117 -0
  136. package/coverage/lcov-report/src/Deck/index.ts.html +239 -0
  137. package/coverage/lcov-report/src/Dictionary/index.html +117 -0
  138. package/coverage/lcov-report/src/Dictionary/index.ts.html +350 -0
  139. package/coverage/lcov-report/src/DoublyLinkedList/Node.ts.html +113 -0
  140. package/coverage/lcov-report/src/DoublyLinkedList/index.html +132 -0
  141. package/coverage/lcov-report/src/DoublyLinkedList/index.ts.html +836 -0
  142. package/coverage/lcov-report/src/HashTable/index.html +117 -0
  143. package/coverage/lcov-report/src/HashTable/index.ts.html +320 -0
  144. package/coverage/lcov-report/src/HashTableLinearProbing/index.html +117 -0
  145. package/coverage/lcov-report/src/HashTableLinearProbing/index.ts.html +95 -0
  146. package/coverage/lcov-report/src/HashTableSeparateChaining/HashTableSeparateChainingElement.ts.html +149 -0
  147. package/coverage/lcov-report/src/HashTableSeparateChaining/index.html +132 -0
  148. package/coverage/lcov-report/src/HashTableSeparateChaining/index.ts.html +398 -0
  149. package/coverage/lcov-report/src/LinkedList/Node.ts.html +110 -0
  150. package/coverage/lcov-report/src/LinkedList/index.html +132 -0
  151. package/coverage/lcov-report/src/LinkedList/index.ts.html +641 -0
  152. package/coverage/lcov-report/src/List/index.html +117 -0
  153. package/coverage/lcov-report/src/List/index.ts.html +89 -0
  154. package/coverage/lcov-report/src/Queue/index.html +117 -0
  155. package/coverage/lcov-report/src/Queue/index.ts.html +218 -0
  156. package/coverage/lcov-report/src/Set/index.html +117 -0
  157. package/coverage/lcov-report/src/Set/index.ts.html +488 -0
  158. package/coverage/lcov-report/src/Stack/index.html +117 -0
  159. package/coverage/lcov-report/src/Stack/index.ts.html +215 -0
  160. package/coverage/lcov-report/src/index.html +117 -0
  161. package/coverage/lcov-report/src/index.ts.html +125 -0
  162. package/coverage/lcov.info +1346 -0
  163. package/package.json +42 -0
  164. package/src/Algorithms/index.spec.ts +15 -0
  165. package/src/Algorithms/index.ts +21 -0
  166. package/src/Array/IArray.ts +10 -0
  167. package/src/Array/index.spec.ts +151 -0
  168. package/src/Array/index.ts +68 -0
  169. package/src/BinarySearchTree/BinarySearchTreeNode.spec.ts +29 -0
  170. package/src/BinarySearchTree/BinarySearchTreeNode.ts +23 -0
  171. package/src/BinarySearchTree/IBinarySearchNodeOptions.ts +6 -0
  172. package/src/BinarySearchTree/IBinarySearchTree.ts +16 -0
  173. package/src/BinarySearchTree/IBinarySearchTreeData.ts +9 -0
  174. package/src/BinarySearchTree/index.spec.ts +486 -0
  175. package/src/BinarySearchTree/index.ts +198 -0
  176. package/src/DataStructure/index.spec.ts +25 -0
  177. package/src/DataStructure/index.ts +15 -0
  178. package/src/Deck/IDeck.ts +10 -0
  179. package/src/Deck/index.spec.ts +131 -0
  180. package/src/Deck/index.ts +51 -0
  181. package/src/Dictionary/IDictionary.ts +18 -0
  182. package/src/Dictionary/IDictionaryData.ts +5 -0
  183. package/src/Dictionary/index.spec.ts +310 -0
  184. package/src/Dictionary/index.ts +88 -0
  185. package/src/DoublyLinkedList/IDoublyLinkedList.ts +18 -0
  186. package/src/DoublyLinkedList/Node.ts +9 -0
  187. package/src/DoublyLinkedList/index.spec.ts +478 -0
  188. package/src/DoublyLinkedList/index.ts +250 -0
  189. package/src/Graph/GraphNodeNotFoundError.ts +7 -0
  190. package/src/Graph/GraphSearchNodeStates.ts +8 -0
  191. package/src/Graph/IGraph.ts +15 -0
  192. package/src/Graph/IGraphOptions.ts +6 -0
  193. package/src/Graph/index.spec.ts +318 -0
  194. package/src/Graph/index.ts +170 -0
  195. package/src/HashTable/IHashTable.ts +11 -0
  196. package/src/HashTable/IHashTableData.ts +5 -0
  197. package/src/HashTable/IHashTableInputs.ts +5 -0
  198. package/src/HashTable/IHashTableOptions.ts +5 -0
  199. package/src/HashTable/index.spec.ts +136 -0
  200. package/src/HashTable/index.ts +78 -0
  201. package/src/HashTableLinearProbing/HashTableLinearProbingElement.spec.ts +28 -0
  202. package/src/HashTableLinearProbing/HashTableLinearProbingElement.ts +18 -0
  203. package/src/HashTableLinearProbing/IHashTableLinearProbing.ts +11 -0
  204. package/src/HashTableLinearProbing/IHashTableLinearProbingData.ts +7 -0
  205. package/src/HashTableLinearProbing/IHashTableLinearProbingInputs.ts +5 -0
  206. package/src/HashTableLinearProbing/IHashTableLinearProbingOptions.ts +5 -0
  207. package/src/HashTableLinearProbing/index.spec.ts +266 -0
  208. package/src/HashTableLinearProbing/index.ts +128 -0
  209. package/src/HashTableSeparateChaining/HashTableSeparateChainingElement.ts +21 -0
  210. package/src/HashTableSeparateChaining/IHashTableSeparateChaining.ts +12 -0
  211. package/src/HashTableSeparateChaining/IHashTableSeparateChainingData.ts +7 -0
  212. package/src/HashTableSeparateChaining/IHashTableSeparateChainingInputs.ts +5 -0
  213. package/src/HashTableSeparateChaining/IHashTableSeparateChainingOptions.ts +5 -0
  214. package/src/HashTableSeparateChaining/index.spec.ts +173 -0
  215. package/src/HashTableSeparateChaining/index.ts +104 -0
  216. package/src/LinkedList/ILinkedList.ts +15 -0
  217. package/src/LinkedList/ILinkedListItem.ts +6 -0
  218. package/src/LinkedList/Node.ts +8 -0
  219. package/src/LinkedList/index.spec.ts +355 -0
  220. package/src/LinkedList/index.ts +185 -0
  221. package/src/List/index.ts +1 -0
  222. package/src/MaxHeap/IMaxHeap.ts +10 -0
  223. package/src/MaxHeap/IMaxHeapOptions.ts +6 -0
  224. package/src/MaxHeap/index.spec.ts +161 -0
  225. package/src/MaxHeap/index.ts +91 -0
  226. package/src/MinHeap/IMinHeap.ts +10 -0
  227. package/src/MinHeap/IMinHeapOptions.ts +6 -0
  228. package/src/MinHeap/index.spec.ts +161 -0
  229. package/src/MinHeap/index.ts +91 -0
  230. package/src/Queue/IQueue.ts +9 -0
  231. package/src/Queue/index.spec.ts +92 -0
  232. package/src/Queue/index.ts +44 -0
  233. package/src/Set/ISet.ts +17 -0
  234. package/src/Set/index.spec.ts +246 -0
  235. package/src/Set/index.ts +134 -0
  236. package/src/Stack/IStack.ts +9 -0
  237. package/src/Stack/index.spec.ts +108 -0
  238. package/src/Stack/index.ts +43 -0
  239. package/src/index.ts +17 -0
  240. package/tsconfig.json +104 -0
@@ -0,0 +1,486 @@
1
+ import {describe, it, expect, jest} from '@jest/globals';
2
+ import faker from 'faker';
3
+
4
+ import BinarySearchTree from './';
5
+
6
+ describe('BinarySearchTree', () => {
7
+ it('Should create an empty bst without problems', () => {
8
+ const bst = new BinarySearchTree();
9
+
10
+ expect(bst.data).toEqual({
11
+ left: null,
12
+ value: null,
13
+ right: null,
14
+ });
15
+ expect(bst.size).toBe(0);
16
+ });
17
+
18
+ it('Should create a filled bst without problems', () => {
19
+ const bst = new BinarySearchTree<number>({
20
+ inputs: [4, 2, 1, 3, 5],
21
+ });
22
+
23
+ expect(bst.data).toEqual({
24
+ left: {
25
+ left: {
26
+ left: null,
27
+ value: 1,
28
+ right: null,
29
+ },
30
+ value: 2,
31
+ right: {
32
+ left: null,
33
+ value: 3,
34
+ right: null,
35
+ },
36
+ },
37
+ value: 4,
38
+ right: {
39
+ left: null,
40
+ value: 5,
41
+ right: null,
42
+ },
43
+ });
44
+ expect(bst.size).toBe(5);
45
+ });
46
+
47
+ it('Should allow us to customize the comparison function', () => {
48
+ const bst = new BinarySearchTree<any[]>({
49
+ lessThanOrEqualTo: (value1: any[], value2: any[]) => {
50
+ if (value1.length <= value2.length) {
51
+ return true;
52
+ }
53
+
54
+ return false;
55
+ },
56
+ inputs: [
57
+ ['one', 'two'],
58
+ ['one'],
59
+ ['one', 'two', 'three'],
60
+ ],
61
+ });
62
+
63
+ expect(bst.data).toEqual({
64
+ left: {
65
+ left: null,
66
+ value: ['one'],
67
+ right: null,
68
+ },
69
+ value: ['one', 'two'],
70
+ right: {
71
+ left: null,
72
+ value: ['one', 'two', 'three'],
73
+ right: null,
74
+ },
75
+ });
76
+ expect(bst.size).toBe(3);
77
+ });
78
+
79
+ describe('.insert()', () => {
80
+ it('Should insert a new value in the root when the root is null', () => {
81
+ const bst = new BinarySearchTree();
82
+ bst.insert(1);
83
+
84
+ expect(bst.data).toEqual({
85
+ left: null,
86
+ value: 1,
87
+ right: null,
88
+ });
89
+ expect(bst.size).toBe(1);
90
+ });
91
+
92
+ it('Should insert a new value in the left of the root when the new value is less than the root value', () => {
93
+ const bst = new BinarySearchTree({
94
+ inputs: [2],
95
+ });
96
+ bst.insert(1);
97
+
98
+ expect(bst.data).toEqual({
99
+ left: {
100
+ left: null,
101
+ value: 1,
102
+ right: null,
103
+ },
104
+ value: 2,
105
+ right: null,
106
+ });
107
+ expect(bst.size).toBe(2);
108
+ });
109
+
110
+ it('Should insert a new value in the left of the root when the new value is equal to the root value', () => {
111
+ const bst = new BinarySearchTree({
112
+ inputs: [1],
113
+ });
114
+ bst.insert(1);
115
+
116
+ expect(bst.data).toEqual({
117
+ left: {
118
+ left: null,
119
+ value: 1,
120
+ right: null,
121
+ },
122
+ value: 1,
123
+ right: null,
124
+ });
125
+ expect(bst.size).toBe(2);
126
+ });
127
+
128
+ it('Should insert a new value in the right of the root when the new value is greater than the root value', () => {
129
+ const bst = new BinarySearchTree({
130
+ inputs: [1],
131
+ });
132
+ bst.insert(2);
133
+
134
+ expect(bst.data).toEqual({
135
+ left: null,
136
+ value: 1,
137
+ right: {
138
+ left: null,
139
+ value: 2,
140
+ right: null,
141
+ },
142
+ });
143
+ expect(bst.size).toBe(2);
144
+ });
145
+
146
+ it('Should return the inserted value', () => {
147
+ const bst = new BinarySearchTree();
148
+ const value = faker.datatype.number();
149
+ const returned = bst.insert(value);
150
+
151
+ expect(returned).toBe(value);
152
+ });
153
+ });
154
+
155
+ describe('.walkInOrder()', () => {
156
+ it('Should walk the tree in order', () => {
157
+ const bst = new BinarySearchTree({
158
+ inputs: [3, 8, 4, 2, 5, 9, 1, 6, 10, 7],
159
+ });
160
+
161
+ const calls: number[] = [];
162
+ const callback = (value: number) => {
163
+ calls.push(value);
164
+ };
165
+
166
+ bst.walkInOrder(callback);
167
+
168
+ expect(calls).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
169
+ });
170
+
171
+ it('Should call the callback function with correct arguments', () => {
172
+ const inputs = [3, 8, 4, 2, 5, 9, 1, 6, 10, 7];
173
+ const bst = new BinarySearchTree({
174
+ inputs,
175
+ });
176
+ const callback = jest.fn();
177
+ bst.walkInOrder(callback);
178
+
179
+ for (const value of inputs) {
180
+ expect(callback).toBeCalledWith(value);
181
+ }
182
+ });
183
+ });
184
+
185
+ describe('.walkPreOrder()', () => {
186
+ it('Should walk the tree pre order', () => {
187
+ const bst = new BinarySearchTree({
188
+ inputs: [3, 8, 4, 2, 5, 9, 1, 6, 10, 7],
189
+ });
190
+
191
+ const calls: number[] = [];
192
+ const callback = (value: number) => {
193
+ calls.push(value);
194
+ };
195
+
196
+ bst.walkPreOrder(callback);
197
+
198
+ expect(calls).toEqual([3, 2, 1, 8, 4, 5, 6, 7, 9, 10]);
199
+ });
200
+
201
+ it('Should call the callback function with correct arguments', () => {
202
+ const inputs = [3, 8, 4, 2, 5, 9, 1, 6, 10, 7];
203
+ const bst = new BinarySearchTree({
204
+ inputs,
205
+ });
206
+ const callback = jest.fn();
207
+ bst.walkPreOrder(callback);
208
+
209
+ for (const value of inputs) {
210
+ expect(callback).toBeCalledWith(value);
211
+ }
212
+ });
213
+ });
214
+
215
+ describe('.walkPostOrder()', () => {
216
+ it('Should walk the tree pre order', () => {
217
+ const bst = new BinarySearchTree({
218
+ inputs: [3, 8, 4, 2, 5, 9, 1, 6, 10, 7],
219
+ });
220
+
221
+ const calls: number[] = [];
222
+ const callback = (value: number) => {
223
+ calls.push(value);
224
+ };
225
+
226
+ bst.walkPostOrder(callback);
227
+
228
+ expect(calls).toEqual([1, 2, 7, 6, 5, 4, 10, 9, 8, 3]);
229
+ });
230
+
231
+ it('Should call the callback function with correct arguments', () => {
232
+ const inputs = [3, 8, 4, 2, 5, 9, 1, 6, 10, 7];
233
+ const bst = new BinarySearchTree({
234
+ inputs,
235
+ });
236
+ const callback = jest.fn();
237
+ bst.walkPostOrder(callback);
238
+
239
+ for (const value of inputs) {
240
+ expect(callback).toBeCalledWith(value);
241
+ }
242
+ });
243
+ });
244
+
245
+ describe('.min', () => {
246
+ it('Should return null when the bst in empty', () => {
247
+ const bst = new BinarySearchTree();
248
+
249
+ expect(bst.min).toBeNull();
250
+ });
251
+
252
+ it('Should return the minimum value of the bst', () => {
253
+ const inputs = new Array(10).fill(undefined).map(faker.datatype.number);
254
+ const bst = new BinarySearchTree({
255
+ inputs,
256
+ });
257
+
258
+ expect(bst.min).toBe(Math.min(...inputs));
259
+ });
260
+ });
261
+
262
+ describe('.max', () => {
263
+ it('Should return null when the bst in empty', () => {
264
+ const bst = new BinarySearchTree();
265
+
266
+ expect(bst.max).toBeNull();
267
+ });
268
+
269
+ it('Should return the maximum value of the bst', () => {
270
+ const inputs = new Array(10).fill(undefined).map(faker.datatype.number);
271
+ const bst = new BinarySearchTree({
272
+ inputs,
273
+ });
274
+
275
+ expect(bst.max).toBe(Math.max(...inputs));
276
+ });
277
+ });
278
+
279
+ describe('.search()', () => {
280
+ it('Should return true when the received value is in the bst', () => {
281
+ const bst = new BinarySearchTree({
282
+ inputs: [3, 2, 4, 1],
283
+ });
284
+ const returned = bst.search(2);
285
+
286
+ expect(returned).toBe(true);
287
+ });
288
+
289
+ it('Should return false whe the received value is not in the bst', () => {
290
+ const bst = new BinarySearchTree({
291
+ inputs: [3, 2, 4, 1],
292
+ });
293
+ const returned = bst.search(5);
294
+
295
+ expect(returned).toBe(false);
296
+ });
297
+ });
298
+
299
+ describe('.remove()', () => {
300
+ it('Should remove a node that is a leaf', () => {
301
+ const bst = new BinarySearchTree({
302
+ inputs: [4, 5, 2, 7, 6, 1],
303
+ });
304
+ bst.remove(6);
305
+
306
+ expect(bst.data).toEqual({
307
+ left: {
308
+ left: {
309
+ left: null,
310
+ value: 1,
311
+ right: null,
312
+ },
313
+ value: 2,
314
+ right: null,
315
+ },
316
+ value: 4,
317
+ right: {
318
+ left: null,
319
+ value: 5,
320
+ right: {
321
+ left: null,
322
+ value: 7,
323
+ right: null,
324
+ },
325
+ },
326
+ });
327
+ expect(bst.size).toBe(5);
328
+ });
329
+
330
+ it('Should remove a node that has a right child', () => {
331
+ const bst = new BinarySearchTree({
332
+ inputs: [4, 5, 2, 7, 6, 1],
333
+ });
334
+ bst.remove(5);
335
+
336
+ expect(bst.data).toEqual({
337
+ left: {
338
+ left: {
339
+ left: null,
340
+ value: 1,
341
+ right: null,
342
+ },
343
+ value: 2,
344
+ right: null,
345
+ },
346
+ value: 4,
347
+ right: {
348
+ left: {
349
+ left: null,
350
+ value: 6,
351
+ right: null,
352
+ },
353
+ value: 7,
354
+ right: null,
355
+ },
356
+ });
357
+ expect(bst.size).toBe(5);
358
+ });
359
+
360
+ it('Should remove a node that has a left child', () => {
361
+ const bst = new BinarySearchTree({
362
+ inputs: [4, 5, 2, 7, 6, 1],
363
+ });
364
+ bst.remove(2);
365
+
366
+ expect(bst.data).toEqual({
367
+ left: {
368
+ left: null,
369
+ right: null,
370
+ value: 1,
371
+ },
372
+ value: 4,
373
+ right: {
374
+ left: null,
375
+ value: 5,
376
+ right: {
377
+ left: {
378
+ left: null,
379
+ value: 6,
380
+ right: null,
381
+ },
382
+ value: 7,
383
+ right: null,
384
+ },
385
+ },
386
+ });
387
+ expect(bst.size).toBe(5);
388
+ });
389
+
390
+ it('Should remove a node thar has a left child and a right child', () => {
391
+ const bst = new BinarySearchTree({
392
+ inputs: [4, 5, 2, 7, 6, 1, 3, 2.5, 2.1, 3.5],
393
+ });
394
+ bst.remove(2);
395
+
396
+ expect(bst.data).toEqual({
397
+ left: {
398
+ left: {
399
+ left: null,
400
+ value: 1,
401
+ right: null,
402
+ },
403
+ value: 2.1,
404
+ right: {
405
+ left: {
406
+ left: null,
407
+ value: 2.5,
408
+ right: null,
409
+ },
410
+ value: 3,
411
+ right: {
412
+ left: null,
413
+ value: 3.5,
414
+ right: null,
415
+ },
416
+ },
417
+ },
418
+ value: 4,
419
+ right: {
420
+ left: null,
421
+ value: 5,
422
+ right: {
423
+ left: {
424
+ left: null,
425
+ value: 6,
426
+ right: null,
427
+ },
428
+ value: 7,
429
+ right: null,
430
+ },
431
+ },
432
+ });
433
+ expect(bst.size).toBe(9);
434
+ });
435
+
436
+ it('Should remove the root', () => {
437
+ const bst = new BinarySearchTree({
438
+ inputs: [4, 5, 2, 7, 6, 1],
439
+ });
440
+ bst.remove(4);
441
+
442
+ expect(bst.data).toEqual({
443
+ left: {
444
+ left: {
445
+ left: null,
446
+ value: 1,
447
+ right: null,
448
+ },
449
+ value: 2,
450
+ right: null,
451
+ },
452
+ value: 5,
453
+ right: {
454
+ left: {
455
+ left: null,
456
+ value: 6,
457
+ right: null,
458
+ },
459
+ value: 7,
460
+ right: null,
461
+ },
462
+ });
463
+ expect(bst.size).toBe(5);
464
+ });
465
+ });
466
+
467
+ describe('Conversion to primitive', () => {
468
+ it('Should return arrow separated values in string conversion', () => {
469
+ const bst = new BinarySearchTree({
470
+ inputs: [4, 2, 1, 3, 6, 5, 7],
471
+ });
472
+ const string = String(bst);
473
+
474
+ expect(string).toBe('[[[null] <= (1) => [null]] <= (2) => [[null] <= (3) => [null]]] <= (4) => [[[null] <= (5) => [null]] <= (6) => [[null] <= (7) => [null]]]');
475
+ });
476
+
477
+ it('Should return the size in number conversion', () => {
478
+ const bst = new BinarySearchTree({
479
+ inputs: [4, 2, 1, 3, 6, 5, 7],
480
+ });
481
+ const number = Number(bst);
482
+
483
+ expect(number).toBe(7);
484
+ });
485
+ });
486
+ });
@@ -0,0 +1,198 @@
1
+ import BinarySearchTreeNode from './BinarySearchTreeNode';
2
+ import IBinarySearchNodeOptions from './IBinarySearchNodeOptions';
3
+ import IBinarySearchTree from './IBinarySearchTree';
4
+ import IBinarySearchTreeData from './IBinarySearchTreeData';
5
+
6
+ export default class BinarySearchTree<T = number> implements IBinarySearchTree<T> {
7
+ private _root: BinarySearchTreeNode<T> | null = null;
8
+ private _size: number = 0;
9
+
10
+ constructor({inputs = [], lessThanOrEqualTo}: IBinarySearchNodeOptions<T> = {inputs: []}) {
11
+ if (lessThanOrEqualTo) {
12
+ this._lessThanOrEqualTo = lessThanOrEqualTo;
13
+ }
14
+
15
+ for (const value of inputs) {
16
+ this.insert(value);
17
+ }
18
+
19
+ this._size = inputs.length;
20
+ }
21
+
22
+ get data(): IBinarySearchTreeData<T> {
23
+ return this._root || {
24
+ left: null,
25
+ value: null,
26
+ right: null,
27
+ };
28
+ }
29
+
30
+ get size(): number {
31
+ return this._size;
32
+ }
33
+
34
+ get min(): T | null {
35
+ let current = this._root;
36
+
37
+ while (current && current.left) {
38
+ current = current.left;
39
+ }
40
+
41
+ return current?.value || null;
42
+ }
43
+
44
+ get max(): T | null {
45
+ let current = this._root;
46
+
47
+ while (current && current.right) {
48
+ current = current.right;
49
+ }
50
+
51
+ return current?.value || null;
52
+ }
53
+
54
+ public insert(value: T): T {
55
+ const node = new BinarySearchTreeNode(value);
56
+
57
+ if (this._root) {
58
+ this._insertChild(this._root, node);
59
+ } else {
60
+ this._root = node;
61
+ }
62
+
63
+ this._size += 1;
64
+
65
+ return value;
66
+ }
67
+
68
+ public walkInOrder(callback: (_value: T) => any): void {
69
+ this._visitNodeInOrder(this._root, callback);
70
+ }
71
+
72
+ public walkPreOrder(callback: (_value: T) => any): void {
73
+ this._visitNodePreOrder(this._root, callback);
74
+ }
75
+
76
+ public walkPostOrder(callback: (_value: T) => any): void {
77
+ this._visitNodePostOrder(this._root, callback);
78
+ }
79
+
80
+ public search(value: T): boolean {
81
+ let current = this._root;
82
+
83
+ while (current && current.value !== value) {
84
+ if (this._lessThanOrEqualTo(value, current.value)) {
85
+ current = current.left;
86
+ } else {
87
+ current = current.right;
88
+ }
89
+ }
90
+
91
+ return Boolean(current);
92
+ }
93
+
94
+ public remove(value: T): T | null {
95
+ let current = this._root;
96
+ const path: Array<'left' | 'right'> = [];
97
+
98
+ while (current && current.value !== value) {
99
+ if (this._lessThanOrEqualTo(value, current.value)) {
100
+ current = current.left;
101
+ path.push('left');
102
+ } else {
103
+ current = current.right;
104
+ path.push('right');
105
+ }
106
+ }
107
+
108
+ const found = {...current};
109
+ const parent = path
110
+ .slice(0, path.length - 1)
111
+ .reduce((accumulator, current) => accumulator && accumulator[current], this._root);
112
+ const child = path[path.length - 1];
113
+
114
+ if (current?.left && current?.right && parent) {
115
+ let head = current.right;
116
+
117
+ while (head.left) {
118
+ head = head.left;
119
+ }
120
+
121
+ this.remove(head.value);
122
+ current.value = head.value;
123
+ } else if (current?.left && parent) {
124
+ parent[child] = current.left;
125
+ this._size -= 1;
126
+ } else if (current?.right && parent) {
127
+ parent[child] = current.right;
128
+ this._size -= 1;
129
+ } else if (parent) {
130
+ parent[child] = null;
131
+ this._size -= 1;
132
+ }
133
+
134
+ return found.value || null;
135
+ }
136
+
137
+ private _lessThanOrEqualTo(value1: T, value2: T): boolean {
138
+ if (value1 <= value2) {
139
+ return true;
140
+ }
141
+
142
+ return false;
143
+ }
144
+
145
+ private _insertChild(father: BinarySearchTreeNode<T>, child: BinarySearchTreeNode<T>): void {
146
+ if (this._lessThanOrEqualTo(child.value, father.value)) {
147
+ if (father.left) {
148
+ this._insertChild(father.left, child);
149
+ } else {
150
+ father.left = child;
151
+ }
152
+
153
+ return;
154
+ }
155
+
156
+ if (father.right) {
157
+ this._insertChild(father.right, child);
158
+ } else {
159
+ father.right = child;
160
+ }
161
+ }
162
+
163
+ private _visitNodeInOrder(node: BinarySearchTreeNode<T> | null, callback: (_value: T) => any): void {
164
+ if (node) {
165
+ this._visitNodeInOrder(node.left, callback);
166
+ callback(node.value);
167
+ this._visitNodeInOrder(node.right, callback);
168
+ }
169
+ }
170
+
171
+ private _visitNodePreOrder(node: BinarySearchTreeNode<T> | null, callback: (_value: T) => any): void {
172
+ if (node) {
173
+ callback(node.value);
174
+ this._visitNodePreOrder(node.left, callback);
175
+ this._visitNodePreOrder(node.right, callback);
176
+ }
177
+ }
178
+
179
+ private _visitNodePostOrder(node: BinarySearchTreeNode<T> | null, callback: (_value: T) => any): void {
180
+ if (node) {
181
+ this._visitNodePostOrder(node.left, callback);
182
+ this._visitNodePostOrder(node.right, callback);
183
+ callback(node.value);
184
+ }
185
+ }
186
+
187
+ private [Symbol.toPrimitive](type: string): string | number | null {
188
+ if (type === 'string') {
189
+ return `${this._root}`;
190
+ }
191
+
192
+ if (type === 'number') {
193
+ return this.size;
194
+ }
195
+
196
+ return null;
197
+ }
198
+ }
@@ -0,0 +1,25 @@
1
+ import {describe, expect, it} from '@jest/globals';
2
+
3
+ import DataStructure from './';
4
+
5
+ describe('DataStructure', () => {
6
+ class Something<T = number> extends DataStructure<T> {
7
+ constructor(...inputs: T[]) {
8
+ super(inputs);
9
+ }
10
+ }
11
+
12
+ it('Should create an empty Something with no problems', () => {
13
+ const something = new Something();
14
+
15
+ expect(something.data).toEqual([]);
16
+ expect(something.size).toBe(0);
17
+ });
18
+
19
+ it('Should create a filled Something with no problems', () => {
20
+ const something = new Something(1, 2, 3, 4);
21
+
22
+ expect(something.data).toEqual([1, 2, 3, 4]);
23
+ expect(something.size).toBe(4);
24
+ });
25
+ });
@@ -0,0 +1,15 @@
1
+ export default abstract class DataStructure<T> {
2
+ protected _data: T[];
3
+
4
+ constructor(inputs: T[]) {
5
+ this._data = [...inputs];
6
+ }
7
+
8
+ public get data(): T[] {
9
+ return [...this._data];
10
+ }
11
+
12
+ public get size(): number {
13
+ return this._data.length;
14
+ }
15
+ }