@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,185 @@
1
+ import ILinkedList from './ILinkedList';
2
+ import Node from './Node';
3
+
4
+ export default class LinkedList<T = number> implements ILinkedList<T> {
5
+ private readonly _FIRST_POSITION = 0;
6
+ private _head: Node<T> | null = null;
7
+ private _size: number = 0;
8
+
9
+ constructor(...inputs: T[]) {
10
+ if (inputs.length) {
11
+ const nodes = inputs.map(input => new Node<T>(input));
12
+
13
+ for (let i = 0; i < inputs.length - 1; i++) {
14
+ nodes[i].next = nodes[i + 1];
15
+ }
16
+
17
+ this._head = nodes[0];
18
+ this._size = nodes.length;
19
+ }
20
+ }
21
+
22
+ public get data() {
23
+ const data = [];
24
+
25
+ let current = this._head;
26
+
27
+ while (current) {
28
+ data.push({
29
+ value: current.value,
30
+ next: current.next?.value || null,
31
+ });
32
+
33
+ current = current.next;
34
+ }
35
+
36
+ return data;
37
+ }
38
+
39
+ public get size() {
40
+ return this._size;
41
+ }
42
+
43
+ public get isEmpty() {
44
+ return this.size === 0;
45
+ }
46
+
47
+ public positionOf(element: T): number | undefined {
48
+ let current = this._head;
49
+ let position = 0;
50
+
51
+ while (current && current.value !== element) {
52
+ current = current?.next;
53
+ position += 1;
54
+ }
55
+
56
+ if (current) {
57
+ return position;
58
+ }
59
+ }
60
+
61
+ public push(element: T): T {
62
+ if (this._head) {
63
+ let current: Node<T> = this._head;
64
+
65
+ while (current.next) {
66
+ current = current.next;
67
+ }
68
+
69
+ current.next = new Node<T>(element);
70
+ } else {
71
+ this._head = new Node<T>(element);
72
+ }
73
+
74
+ this._size += 1;
75
+
76
+ return element;
77
+ }
78
+
79
+ public remove(element: T): T | undefined {
80
+ const position = this.positionOf(element);
81
+
82
+ if (position) {
83
+ return this.removeFromPosition(position);
84
+ }
85
+ }
86
+
87
+ public insertInPosition(element: T, position: number): T | undefined {
88
+ if (position < this._FIRST_POSITION || position > this.size) {
89
+ return undefined;
90
+ }
91
+
92
+ const node = new Node<T>(element);
93
+
94
+ if (position === this._FIRST_POSITION) {
95
+ node.next = this._head;
96
+ this._head = node;
97
+ } else {
98
+ const before = this.getNodeFromPosition(position - 1);
99
+ const after = (before && before.next) || null;
100
+
101
+ if (before) {
102
+ before.next = node;
103
+ }
104
+
105
+ node.next = after;
106
+ }
107
+
108
+ this._size += 1;
109
+
110
+ return element;
111
+ }
112
+
113
+ public getFromPosition(position: number) {
114
+ if (position < this._FIRST_POSITION || position > this.size - 1) {
115
+ return undefined;
116
+ }
117
+
118
+ let node = this._head;
119
+
120
+ for (let i = 0; i < position; i++) {
121
+ node = node?.next || null;
122
+ }
123
+
124
+ if (node?.value) {
125
+ return {
126
+ value: node.value,
127
+ next: node.next?.value || null,
128
+ };
129
+ }
130
+
131
+ return undefined;
132
+ }
133
+
134
+ public removeFromPosition(position: number): T | undefined {
135
+ if (position < this._FIRST_POSITION || position > (this.size - 1)) {
136
+ return undefined;
137
+ }
138
+
139
+ let current: Node<T> | null = this._head;
140
+
141
+ if (position === this._FIRST_POSITION) {
142
+ this._head = current?.next || null;
143
+ } else {
144
+ let previous: Node<T> | null | undefined;
145
+
146
+ for (let i = 0; i < position; i++) {
147
+ previous = current;
148
+ current = current?.next || null;
149
+ }
150
+
151
+ if (previous) {
152
+ previous.next = current?.next || null;
153
+ }
154
+ }
155
+
156
+ this._size -= 1;
157
+ return current?.value;
158
+ }
159
+
160
+ private getNodeFromPosition(position: number): Node<T> | undefined {
161
+ if (position < this._FIRST_POSITION || position > this.size - 1) {
162
+ return undefined;
163
+ }
164
+
165
+ let node = this._head;
166
+
167
+ for (let i = 0; i < position; i++) {
168
+ node = node?.next || null;
169
+ }
170
+
171
+ return node || undefined;
172
+ }
173
+
174
+ private [Symbol.toPrimitive](type: string): string | number | null {
175
+ if (type === 'string') {
176
+ return `[Head] ${this.data.map(({value}) => value).join(' => ')}`;
177
+ }
178
+
179
+ if (type === 'number') {
180
+ return this.size;
181
+ }
182
+
183
+ return null;
184
+ }
185
+ }
@@ -0,0 +1 @@
1
+ export {default} from '../Array';
@@ -0,0 +1,10 @@
1
+ interface IMaxHeap<T> {
2
+ get data(): T[];
3
+ get size(): number;
4
+ get isEmpty(): boolean;
5
+ get max(): T | null;
6
+ insert(_value: T): T;
7
+ extract(): T | null;
8
+ }
9
+
10
+ export default IMaxHeap;
@@ -0,0 +1,6 @@
1
+ interface IMaxHeapOptions<T> {
2
+ greaterThanOrEqualTo?: (_value1: T, _value2: T) => boolean;
3
+ inputs?: T[],
4
+ }
5
+
6
+ export default IMaxHeapOptions;
@@ -0,0 +1,161 @@
1
+ import {describe, it, expect} from '@jest/globals';
2
+ import faker from 'faker';
3
+
4
+ import MaxHeap from './';
5
+
6
+ describe('MaxHeap', () => {
7
+ it('Should create an empty max heap without problems', () => {
8
+ const maxHeap = new MaxHeap();
9
+
10
+ expect(maxHeap.data).toEqual([]);
11
+ expect(maxHeap.size).toBe(0);
12
+ });
13
+
14
+ it('Should create a filled max heap without problems', () => {
15
+ const maxHeap = new MaxHeap({
16
+ inputs: [5, 2, 1, 9],
17
+ });
18
+
19
+ expect(maxHeap.data).toEqual([9, 5, 1, 2]);
20
+ expect(maxHeap.size).toBe(4);
21
+ });
22
+
23
+ describe('.isEmpty', () => {
24
+ it('Should be true when the heap has no values', () => {
25
+ const maxHeap = new MaxHeap();
26
+
27
+ expect(maxHeap.isEmpty).toBe(true);
28
+ });
29
+
30
+ it('Should be false when the heap has at least one value', () => {
31
+ const maxHeap = new MaxHeap({
32
+ inputs: [faker.datatype.number()],
33
+ });
34
+
35
+ expect(maxHeap.isEmpty).toBe(false);
36
+ });
37
+ });
38
+
39
+ describe('.max', () => {
40
+ it('Should be the min value when the heap is not empty', () => {
41
+ const inputs = new Array(10).fill(undefined).map(faker.datatype.number);
42
+ const maxHeap = new MaxHeap({
43
+ inputs,
44
+ });
45
+
46
+ expect(maxHeap.max).toBe(Math.max(...inputs));
47
+ });
48
+
49
+ it('Should be null when the heap is empty', () => {
50
+ const maxHeap = new MaxHeap();
51
+
52
+ expect(maxHeap.max).toBeNull();
53
+ });
54
+ });
55
+
56
+ describe('.insert()', () => {
57
+ it('Should insert new values in the heap', () => {
58
+ const maxHeap = new MaxHeap();
59
+
60
+ maxHeap.insert(5);
61
+ expect(maxHeap.data).toEqual([5]);
62
+ expect(maxHeap.size).toBe(1);
63
+
64
+ maxHeap.insert(2);
65
+ expect(maxHeap.data).toEqual([5, 2]);
66
+ expect(maxHeap.size).toBe(2);
67
+
68
+ maxHeap.insert(1);
69
+ expect(maxHeap.data).toEqual([5, 2, 1]);
70
+ expect(maxHeap.size).toBe(3);
71
+
72
+ maxHeap.insert(9);
73
+ expect(maxHeap.data).toEqual([9, 5, 1, 2]);
74
+ expect(maxHeap.size).toBe(4);
75
+ });
76
+
77
+ it('Should return the inserted value', () => {
78
+ const maxHeap = new MaxHeap();
79
+ const value = faker.datatype.number();
80
+ const returned = maxHeap.insert(value);
81
+
82
+ expect(returned).toBe(value);
83
+ });
84
+ });
85
+
86
+ describe('.extract()', () => {
87
+ it('Should extract the max value of the heap and adjust the heap after this', () => {
88
+ const maxHeap = new MaxHeap({
89
+ inputs: [9, 8, 7, 6, 5, 4, 3, 2, 1],
90
+ });
91
+ maxHeap.extract();
92
+
93
+ expect(maxHeap.data).toEqual([8, 6, 7, 2, 5, 4, 3, 1]);
94
+ expect(maxHeap.size).toBe(8);
95
+ });
96
+
97
+ it('Should return the extracted value', () => {
98
+ const inputs = new Array(10).fill(undefined).map(faker.datatype.number);
99
+ const maxHeap = new MaxHeap({inputs});
100
+ const returned = maxHeap.extract();
101
+
102
+ expect(returned).toBe(Math.max(...inputs));
103
+ });
104
+
105
+ it('Should change nothing if the heap is empty', () => {
106
+ const maxHeap = new MaxHeap();
107
+ maxHeap.extract();
108
+
109
+ expect(maxHeap.data).toEqual([]);
110
+ expect(maxHeap.size).toBe(0);
111
+ });
112
+ });
113
+
114
+ describe('Heap Sort', () => {
115
+ it('Should sort an array in DESC order', () => {
116
+ const maxHeap = new MaxHeap({
117
+ inputs: [
118
+ 7,
119
+ 1,
120
+ 10,
121
+ 4,
122
+ 8,
123
+ 6,
124
+ 2,
125
+ 3,
126
+ 5,
127
+ 9,
128
+ ],
129
+ });
130
+
131
+ const {size} = maxHeap;
132
+ const result = [];
133
+
134
+ for (let i = 1; i <= size; i++) {
135
+ result.push(maxHeap.extract());
136
+ }
137
+
138
+ expect(result).toEqual([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
139
+ });
140
+ });
141
+
142
+ describe('Conversion to primitive', () => {
143
+ it('Should return separated by comma values in string conversion', () => {
144
+ const maxHeap = new MaxHeap({
145
+ inputs: [1, 2, 3, 4, 5],
146
+ });
147
+ const string = String(maxHeap);
148
+
149
+ expect(string).toBe('5, 4, 2, 1, 3');
150
+ });
151
+
152
+ it('Should return the size in number conversion', () => {
153
+ const maxHeap = new MaxHeap({
154
+ inputs: [1, 2, 3, 4, 5],
155
+ });
156
+ const number = Number(maxHeap);
157
+
158
+ expect(number).toBe(5);
159
+ });
160
+ });
161
+ });
@@ -0,0 +1,91 @@
1
+ import IMaxHeap from './IMaxHeap';
2
+ import IMaxHeapOptions from './IMaxHeapOptions';
3
+
4
+ export default class MaxHeap<T = number> implements IMaxHeap<T> {
5
+ private _data: T[] = [];
6
+
7
+ constructor({greaterThanOrEqualTo, inputs = []}: IMaxHeapOptions<T> = {inputs: []}) {
8
+ if (greaterThanOrEqualTo) {
9
+ this._greaterThanOrEqualTo = greaterThanOrEqualTo;
10
+ }
11
+
12
+ for (const input of inputs) {
13
+ this.insert(input);
14
+ }
15
+ }
16
+
17
+ get data(): T[] {
18
+ return [...this._data];
19
+ }
20
+
21
+ get size(): number {
22
+ return this.data.length;
23
+ }
24
+
25
+ get isEmpty(): boolean {
26
+ return this.size === 0;
27
+ }
28
+
29
+ get max(): T | null {
30
+ return this.data[0] || null;
31
+ }
32
+
33
+ public insert(value: T): T {
34
+ this._data = [...this.data, value];
35
+ this._siftUp(this.size - 1);
36
+ return value;
37
+ }
38
+
39
+ public extract(): T | null {
40
+ if (!this.isEmpty) {
41
+ const [min, ...rest] = this.data;
42
+ this._data = [rest[rest.length - 1], ...rest.slice(0, rest.length - 1)].filter(value => value !== undefined);
43
+ this._siftDown(0);
44
+
45
+ return min;
46
+ }
47
+
48
+ return null;
49
+ }
50
+
51
+ private _greaterThanOrEqualTo = (value1: T, value2: T): boolean => value1 >= value2;
52
+ private _getLeftIndex = (index: number): number => (2 * index) + 1;
53
+ private _getRightIndex = (index: number): number => (2 * index) + 2;
54
+ private _getParentIndex = (index: number): number => Math.floor((index - 1) / 2);
55
+
56
+ private _siftUp(index: number): void {
57
+ const parent = this._getParentIndex(index);
58
+
59
+ if (index > 0 && this._greaterThanOrEqualTo(this.data[index], this.data[parent])) {
60
+ [this._data[parent], this._data[index]] = [this.data[index], this.data[parent]];
61
+ this._siftUp(parent);
62
+ }
63
+ }
64
+
65
+ private _siftDown(index: number): void {
66
+ const left = this._getLeftIndex(index);
67
+ const right = this._getRightIndex(index);
68
+
69
+ if (left < this.size && this._greaterThanOrEqualTo(this.data[left], this.data[index])) {
70
+ [this._data[left], this._data[index]] = [this.data[index], this.data[left]];
71
+ this._siftDown(left);
72
+ }
73
+
74
+ if (right < this.size && this._greaterThanOrEqualTo(this.data[right], this.data[index])) {
75
+ [this._data[right], this._data[index]] = [this.data[index], this.data[right]];
76
+ this._siftDown(right);
77
+ }
78
+ }
79
+
80
+ private [Symbol.toPrimitive](type: string): string | number | null {
81
+ if (type === 'string') {
82
+ return this.data.join(', ');
83
+ }
84
+
85
+ if (type === 'number') {
86
+ return this.size;
87
+ }
88
+
89
+ return null;
90
+ }
91
+ }
@@ -0,0 +1,10 @@
1
+ interface IMinHeap<T> {
2
+ get data(): T[];
3
+ get size(): number;
4
+ get isEmpty(): boolean;
5
+ get min(): T | null;
6
+ insert(_value: T): T;
7
+ extract(): T | null;
8
+ }
9
+
10
+ export default IMinHeap;
@@ -0,0 +1,6 @@
1
+ interface IMinHeapOptions<T> {
2
+ lessThanOrEqualTo?: (_value1: T, _value2: T) => boolean;
3
+ inputs?: T[],
4
+ }
5
+
6
+ export default IMinHeapOptions;
@@ -0,0 +1,161 @@
1
+ import {describe, it, expect} from '@jest/globals';
2
+ import faker from 'faker';
3
+
4
+ import MinHeap from './';
5
+
6
+ describe('MinHeap', () => {
7
+ it('Should create an empty min heap without problems', () => {
8
+ const minHeap = new MinHeap();
9
+
10
+ expect(minHeap.data).toEqual([]);
11
+ expect(minHeap.size).toBe(0);
12
+ });
13
+
14
+ it('Should create a filled min heap without problems', () => {
15
+ const minHeap = new MinHeap({
16
+ inputs: [5, 2, 1, 9],
17
+ });
18
+
19
+ expect(minHeap.data).toEqual([1, 5, 2, 9]);
20
+ expect(minHeap.size).toBe(4);
21
+ });
22
+
23
+ describe('.isEmpty', () => {
24
+ it('Should be true when the heap has no values', () => {
25
+ const minHeap = new MinHeap();
26
+
27
+ expect(minHeap.isEmpty).toBe(true);
28
+ });
29
+
30
+ it('Should be false when the heap has at least one value', () => {
31
+ const minHeap = new MinHeap({
32
+ inputs: [faker.datatype.number()],
33
+ });
34
+
35
+ expect(minHeap.isEmpty).toBe(false);
36
+ });
37
+ });
38
+
39
+ describe('.min', () => {
40
+ it('Should be the min value when the heap is not empty', () => {
41
+ const inputs = new Array(10).fill(undefined).map(faker.datatype.number);
42
+ const minHeap = new MinHeap({
43
+ inputs,
44
+ });
45
+
46
+ expect(minHeap.min).toBe(Math.min(...inputs));
47
+ });
48
+
49
+ it('Should be null when the heap is empty', () => {
50
+ const minHeap = new MinHeap();
51
+
52
+ expect(minHeap.min).toBeNull();
53
+ });
54
+ });
55
+
56
+ describe('.insert()', () => {
57
+ it('Should insert new values in the heap', () => {
58
+ const minHeap = new MinHeap();
59
+
60
+ minHeap.insert(5);
61
+ expect(minHeap.data).toEqual([5]);
62
+ expect(minHeap.size).toBe(1);
63
+
64
+ minHeap.insert(2);
65
+ expect(minHeap.data).toEqual([2, 5]);
66
+ expect(minHeap.size).toBe(2);
67
+
68
+ minHeap.insert(1);
69
+ expect(minHeap.data).toEqual([1, 5, 2]);
70
+ expect(minHeap.size).toBe(3);
71
+
72
+ minHeap.insert(9);
73
+ expect(minHeap.data).toEqual([1, 5, 2, 9]);
74
+ expect(minHeap.size).toBe(4);
75
+ });
76
+
77
+ it('Should return the inserted value', () => {
78
+ const minHeap = new MinHeap();
79
+ const value = faker.datatype.number();
80
+ const returned = minHeap.insert(value);
81
+
82
+ expect(returned).toBe(value);
83
+ });
84
+ });
85
+
86
+ describe('.extract()', () => {
87
+ it('Should extract the min value of the heap and adjust the heap after this', () => {
88
+ const minHeap = new MinHeap({
89
+ inputs: [1, 2, 3, 4, 5, 6, 7, 8, 9],
90
+ });
91
+ minHeap.extract();
92
+
93
+ expect(minHeap.data).toEqual([2, 4, 3, 8, 5, 6, 7, 9]);
94
+ expect(minHeap.size).toBe(8);
95
+ });
96
+
97
+ it('Should return the extracted value', () => {
98
+ const inputs = new Array(10).fill(undefined).map(faker.datatype.number);
99
+ const minHeap = new MinHeap({inputs});
100
+ const returned = minHeap.extract();
101
+
102
+ expect(returned).toBe(Math.min(...inputs));
103
+ });
104
+
105
+ it('Should change nothing if the heap is empty', () => {
106
+ const minHeap = new MinHeap();
107
+ minHeap.extract();
108
+
109
+ expect(minHeap.data).toEqual([]);
110
+ expect(minHeap.size).toBe(0);
111
+ });
112
+ });
113
+
114
+ describe('Heap Sort', () => {
115
+ it('Should sort an array in ASC order', () => {
116
+ const minHeap = new MinHeap({
117
+ inputs: [
118
+ 7,
119
+ 1,
120
+ 10,
121
+ 4,
122
+ 8,
123
+ 6,
124
+ 2,
125
+ 3,
126
+ 5,
127
+ 9,
128
+ ],
129
+ });
130
+
131
+ const {size} = minHeap;
132
+ const result = [];
133
+
134
+ for (let i = 1; i <= size; i++) {
135
+ result.push(minHeap.extract());
136
+ }
137
+
138
+ expect(result).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
139
+ });
140
+ });
141
+
142
+ describe('Conversion to primitive', () => {
143
+ it('Should return separated by comma values in string conversion', () => {
144
+ const maxHeap = new MinHeap({
145
+ inputs: [1, 2, 3, 4, 5],
146
+ });
147
+ const string = String(maxHeap);
148
+
149
+ expect(string).toBe('1, 2, 3, 4, 5');
150
+ });
151
+
152
+ it('Should return the size in number conversion', () => {
153
+ const maxHeap = new MinHeap({
154
+ inputs: [1, 2, 3, 4, 5],
155
+ });
156
+ const number = Number(maxHeap);
157
+
158
+ expect(number).toBe(5);
159
+ });
160
+ });
161
+ });