heap-typed 1.53.5 → 1.53.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,225 +30,190 @@ npm i heap-typed --save
30
30
  yarn add heap-typed
31
31
  ```
32
32
 
33
- ### methods
34
-
35
- Min Heap
36
- ![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/methods-8bit/min-heap.png?raw=true)
37
- Max Heap
38
- ![](https://github.com/zrwusa/assets/blob/master/images/data-structure-typed/methods-8bit/max-heap.png?raw=true)
39
-
40
33
  ### snippet
41
34
 
42
- #### heap sort TS
35
+ [//]: # (No deletion!!! Start of Example Replace Section)
43
36
 
37
+ ### Use Heap to sort an array
44
38
  ```typescript
45
- import {Heap, MaxHeap, MinHeap} from 'data-structure-typed';
46
-
47
- // /* or if you prefer */ import {MinHeap, MaxHeap} from 'heap-typed';
48
-
49
- // Use Heap to sort an array
50
39
  function heapSort(arr: number[]): number[] {
51
- const heap = new Heap<number>(arr, {comparator: (a, b) => a - b});
52
- const sorted: number[] = [];
53
- while (!heap.isEmpty()) {
40
+ const heap = new Heap<number>(arr, { comparator: (a, b) => a - b });
41
+ const sorted: number[] = [];
42
+ while (!heap.isEmpty()) {
54
43
  sorted.push(heap.poll()!); // Poll minimum element
44
+ }
45
+ return sorted;
55
46
  }
56
- return sorted;
57
- }
58
-
59
- console.log('Heap sorted:', heapSort([5, 3, 8, 4, 1, 2])); // [1, 2, 3, 4, 5, 8];
60
47
 
48
+ const array = [5, 3, 8, 4, 1, 2];
49
+ console.log(heapSort(array)); // [1, 2, 3, 4, 5, 8]
61
50
  ```
62
51
 
63
-
64
- #### top K problem TS
65
-
52
+ ### Use Heap to solve top k problems
66
53
  ```typescript
67
- // Use Heap to resolve top K problem
68
54
  function topKElements(arr: number[], k: number): number[] {
69
- const heap = new Heap<number>([], {comparator: (a, b) => b - a}); // Max heap
70
- arr.forEach((num) => {
55
+ const heap = new Heap<number>([], { comparator: (a, b) => b - a }); // Max heap
56
+ arr.forEach(num => {
71
57
  heap.add(num);
72
58
  if (heap.size > k) heap.poll(); // Keep the heap size at K
73
- });
74
- return heap.toArray();
75
- }
59
+ });
60
+ return heap.toArray();
61
+ }
76
62
 
77
- const numbers = [10, 30, 20, 5, 15, 25];
78
- console.log('Top K:', topKElements(numbers, 3)); // [15, 10, 5]
63
+ const numbers = [10, 30, 20, 5, 15, 25];
64
+ console.log(topKElements(numbers, 3)); // [15, 10, 5]
79
65
  ```
80
66
 
81
- #### real-time median TS
67
+ ### Use Heap to merge sorted sequences
68
+ ```typescript
69
+ function mergeSortedSequences(sequences: number[][]): number[] {
70
+ const heap = new Heap<{ value: number; seqIndex: number; itemIndex: number }>([], {
71
+ comparator: (a, b) => a.value - b.value // Min heap
72
+ });
73
+
74
+ // Initialize heap
75
+ sequences.forEach((seq, seqIndex) => {
76
+ if (seq.length) {
77
+ heap.add({ value: seq[0], seqIndex, itemIndex: 0 });
78
+ }
79
+ });
80
+
81
+ const merged: number[] = [];
82
+ while (!heap.isEmpty()) {
83
+ const { value, seqIndex, itemIndex } = heap.poll()!;
84
+ merged.push(value);
85
+
86
+ if (itemIndex + 1 < sequences[seqIndex].length) {
87
+ heap.add({
88
+ value: sequences[seqIndex][itemIndex + 1],
89
+ seqIndex,
90
+ itemIndex: itemIndex + 1
91
+ });
92
+ }
93
+ }
94
+
95
+ return merged;
96
+ }
97
+
98
+ const sequences = [
99
+ [1, 4, 7],
100
+ [2, 5, 8],
101
+ [3, 6, 9]
102
+ ];
103
+ console.log(mergeSortedSequences(sequences)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
104
+ ```
82
105
 
106
+ ### Use Heap to dynamically maintain the median
83
107
  ```typescript
84
- // Use Heap to maintain median value for real-time retrieval
85
108
  class MedianFinder {
86
- private low: MaxHeap<number>; // Max heap, stores the smaller half
87
- private high: MinHeap<number>; // Min heap, stores the larger half
109
+ private low: MaxHeap<number>; // Max heap, stores the smaller half
110
+ private high: MinHeap<number>; // Min heap, stores the larger half
88
111
 
89
- constructor() {
112
+ constructor() {
90
113
  this.low = new MaxHeap<number>([]);
91
114
  this.high = new MinHeap<number>([]);
92
- }
115
+ }
93
116
 
94
- addNum(num: number): void {
117
+ addNum(num: number): void {
95
118
  if (this.low.isEmpty() || num <= this.low.peek()!) this.low.add(num);
96
119
  else this.high.add(num);
97
120
 
98
121
  // Balance heaps
99
122
  if (this.low.size > this.high.size + 1) this.high.add(this.low.poll()!);
100
123
  else if (this.high.size > this.low.size) this.low.add(this.high.poll()!);
101
- }
124
+ }
102
125
 
103
- findMedian(): number {
126
+ findMedian(): number {
127
+ if (this.low.size === this.high.size) return (this.low.peek()! + this.high.peek()!) / 2;
104
128
  return this.low.peek()!;
129
+ }
105
130
  }
106
- }
107
-
108
- const medianFinder = new MedianFinder();
109
- medianFinder.addNum(10);
110
- console.log('realtime median: ', medianFinder.findMedian()) // 10
111
- medianFinder.addNum(20);
112
- console.log('realtime median: ', medianFinder.findMedian()) // 10
113
- medianFinder.addNum(30);
114
- console.log('realtime median: ', medianFinder.findMedian()) // 20
115
- medianFinder.addNum(40);
116
- console.log('realtime median: ', medianFinder.findMedian()) // 20
117
- medianFinder.addNum(50);
118
- console.log('realtime median: ', medianFinder.findMedian()) // 30
119
- ```
120
131
 
121
- #### load balance TS
132
+ const medianFinder = new MedianFinder();
133
+ medianFinder.addNum(10);
134
+ console.log(medianFinder.findMedian()); // 10
135
+ medianFinder.addNum(20);
136
+ console.log(medianFinder.findMedian()); // 15
137
+ medianFinder.addNum(30);
138
+ console.log(medianFinder.findMedian()); // 20
139
+ medianFinder.addNum(40);
140
+ console.log(medianFinder.findMedian()); // 25
141
+ medianFinder.addNum(50);
142
+ console.log(medianFinder.findMedian()); // 30
143
+ ```
122
144
 
145
+ ### Use Heap for load balancing
123
146
  ```typescript
124
- // Use Heap for load balancing
125
147
  function loadBalance(requests: number[], servers: number): number[] {
126
- const serverHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // min heap
127
- const serverLoads = new Array(servers).fill(0);
148
+ const serverHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // min heap
149
+ const serverLoads = new Array(servers).fill(0);
128
150
 
129
- for (let i = 0; i < servers; i++) {
151
+ for (let i = 0; i < servers; i++) {
130
152
  serverHeap.add({ id: i, load: 0 });
131
- }
153
+ }
132
154
 
133
- requests.forEach(req => {
155
+ requests.forEach(req => {
134
156
  const server = serverHeap.poll()!;
135
157
  serverLoads[server.id] += req;
136
158
  server.load += req;
137
159
  serverHeap.add(server); // The server after updating the load is re-entered into the heap
138
- });
160
+ });
139
161
 
140
- return serverLoads;
141
- }
162
+ return serverLoads;
163
+ }
142
164
 
143
- const requests = [5, 2, 8, 3, 7];
144
- const serversLoads = loadBalance(requests, 3);
145
- console.log('server loads: ', serversLoads); // [12, 8, 5]
165
+ const requests = [5, 2, 8, 3, 7];
166
+ console.log(loadBalance(requests, 3)); // [12, 8, 5]
146
167
  ```
147
- #### conventional operation TS
148
168
 
169
+ ### Use Heap to schedule tasks
149
170
  ```typescript
150
- const minNumHeap = new MinHeap<number>([1, 6, 2, 0, 5]);
151
- minNumHeap.add(9);
152
- minNumHeap.has(1) // true
153
- minNumHeap.has(2) // true
154
- minNumHeap.poll() // 0
155
- minNumHeap.poll() // 1
156
- minNumHeap.peek() // 2
157
- minNumHeap.has(1); // false
158
- minNumHeap.has(2); // true
159
-
160
- const arrFromHeap = minNumHeap.toArray();
161
- arrFromHeap.length // 4
162
- arrFromHeap[0] // 2
163
- arrFromHeap[1] // 5
164
- arrFromHeap[2] // 9
165
- arrFromHeap[3] // 6
166
- minNumHeap.sort() // [2, 5, 6, 9]
167
-
168
- const maxHeap = new MaxHeap<{ keyA: string }>([], {comparator: (a, b) => b.keyA - a.keyA});
169
- const obj1 = {keyA: 'a1'}, obj6 = {keyA: 'a6'}, obj5 = {keyA: 'a5'}, obj2 = {keyA: 'a2'},
170
- obj0 = {keyA: 'a0'}, obj9 = {keyA: 'a9'};
171
-
172
- maxHeap.add(obj1);
173
- maxHeap.has(obj1) // true
174
- maxHeap.has(obj9) // false
175
- maxHeap.add(obj6);
176
- maxHeap.has(obj6) // true
177
- maxHeap.add(obj5);
178
- maxHeap.add(obj2);
179
- maxHeap.add(obj0);
180
- maxHeap.add(obj9);
181
- maxHeap.has(obj9) // true
182
-
183
- const peek9 = maxHeap.peek();
184
- console.log(peek9.keyA) // 'a9'
185
-
186
- const heapToArr = maxHeap.toArray();
187
- console.log(heapToArr.map(ele => ele?.keyA)); // ['a9', 'a2', 'a6', 'a1', 'a0', 'a5']
188
-
189
- const values = ['a9', 'a6', 'a5', 'a2', 'a1', 'a0'];
190
- let i = 0;
191
- while (maxHeap.size > 0) {
192
- const polled = maxHeap.poll();
193
- console.log(polled.keyA) // values[i]
194
- i++;
195
- }
196
- ```
171
+ type Task = [string, number];
172
+
173
+ function scheduleTasks(tasks: Task[], machines: number): Map<number, Task[]> {
174
+ const machineHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // Min heap
175
+ const allocation = new Map<number, Task[]>();
176
+
177
+ // Initialize the load on each machine
178
+ for (let i = 0; i < machines; i++) {
179
+ machineHeap.add({ id: i, load: 0 });
180
+ allocation.set(i, []);
181
+ }
182
+
183
+ // Assign tasks
184
+ tasks.forEach(([task, load]) => {
185
+ const machine = machineHeap.poll()!;
186
+ allocation.get(machine.id)!.push([task, load]);
187
+ machine.load += load;
188
+ machineHeap.add(machine); // The machine after updating the load is re-entered into the heap
189
+ });
190
+
191
+ return allocation;
192
+ }
197
193
 
198
- #### conventional operation JS
199
-
200
- ```javascript
201
- const {MinHeap, MaxHeap} = require('data-structure-typed');
202
- // /* or if you prefer */ const {MinHeap, MaxHeap} = require('heap-typed');
203
-
204
- const minNumHeap = new MinHeap([1, 6, 2, 0, 5]);
205
- minNumHeap.add(9);
206
- minNumHeap.has(1) // true
207
- minNumHeap.has(2) // true
208
- minNumHeap.poll() // 0
209
- minNumHeap.poll() // 1
210
- minNumHeap.peek() // 2
211
- minNumHeap.has(1); // false
212
- minNumHeap.has(2); // true
213
-
214
- const arrFromHeap = minNumHeap.toArray();
215
- arrFromHeap.length // 4
216
- arrFromHeap[0] // 2
217
- arrFromHeap[1] // 5
218
- arrFromHeap[2] // 9
219
- arrFromHeap[3] // 6
220
- minNumHeap.sort() // [2, 5, 6, 9]
221
-
222
- const maxHeap = new MaxHeap([], {comparator: (a, b) => b.keyA - a.keyA});
223
- const obj1 = {keyA: 'a1'}, obj6 = {keyA: 'a6'}, obj5 = {keyA: 'a5'}, obj2 = {keyA: 'a2'},
224
- obj0 = {keyA: 'a0'}, obj9 = {keyA: 'a9'};
225
-
226
- maxHeap.add(obj1);
227
- maxHeap.has(obj1) // true
228
- maxHeap.has(obj9) // false
229
- maxHeap.add(obj6);
230
- maxHeap.has(obj6) // true
231
- maxHeap.add(obj5);
232
- maxHeap.add(obj2);
233
- maxHeap.add(obj0);
234
- maxHeap.add(obj9);
235
- maxHeap.has(obj9) // true
236
-
237
- const peek9 = maxHeap.peek();
238
- console.log(peek9.keyA) // 'a9'
239
-
240
- const heapToArr = maxHeap.toArray();
241
- console.log(heapToArr.map(ele => ele?.keyA)); // ['a9', 'a2', 'a6', 'a1', 'a0', 'a5']
242
-
243
- const values = ['a9', 'a6', 'a5', 'a2', 'a1', 'a0'];
244
- let i = 0;
245
- while (maxHeap.size > 0) {
246
- const polled = maxHeap.poll();
247
- console.log(polled.keyA) // values[i]
248
- i++;
249
- }
194
+ const tasks: Task[] = [
195
+ ['Task1', 3],
196
+ ['Task2', 1],
197
+ ['Task3', 2],
198
+ ['Task4', 5],
199
+ ['Task5', 4]
200
+ ];
201
+ const expectedMap = new Map<number, Task[]>();
202
+ expectedMap.set(0, [
203
+ ['Task1', 3],
204
+ ['Task4', 5]
205
+ ]);
206
+ expectedMap.set(1, [
207
+ ['Task2', 1],
208
+ ['Task3', 2],
209
+ ['Task5', 4]
210
+ ]);
211
+ console.log(scheduleTasks(tasks, 2)); // expectedMap
250
212
  ```
251
213
 
214
+ [//]: # (No deletion!!! End of Example Replace Section)
215
+
216
+
252
217
 
253
218
  ## API docs & Examples
254
219
 
@@ -709,22 +709,18 @@ export declare class DoublyLinkedList<E = any, R = any> extends IterableElementB
709
709
  * Time Complexity: O(n)
710
710
  * Space Complexity: O(1)
711
711
  *
712
- * The indexOf function in TypeScript returns the index of a specified element or node in a Doubly
713
- * Linked List.
714
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
715
- * `indexOf` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an
716
- * element of type `E`.
717
- * @returns The `indexOf` method is returning the index of the element or node in the doubly linked
718
- * list. If the element or node is found in the list, the method returns the index of that element or
719
- * node. If the element or node is not found in the list, the method returns -1.
712
+ * This function finds the index of a specified element, node, or predicate in a doubly linked list.
713
+ * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
714
+ * elementNodeOrPredicate - The `indexOf` method takes in a parameter `elementNodeOrPredicate`, which
715
+ * can be one of the following:
716
+ * @returns The `indexOf` method returns the index of the element in the doubly linked list that
717
+ * matches the provided element, node, or predicate. If no match is found, it returns -1.
720
718
  */
721
- indexOf(elementOrNode: E | DoublyLinkedListNode<E>): number;
719
+ indexOf(elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number;
722
720
  /**
723
721
  * Time Complexity: O(n)
724
722
  * Space Complexity: O(1)
725
723
  *
726
- */
727
- /**
728
724
  * This function retrieves an element from a doubly linked list based on a given element
729
725
  * node or predicate.
730
726
  * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
@@ -820,6 +816,12 @@ export declare class DoublyLinkedList<E = any, R = any> extends IterableElementB
820
816
  * @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.
821
817
  */
822
818
  map<EM, RM>(callback: ElementCallback<E, R, EM, DoublyLinkedList<E, R>>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): DoublyLinkedList<EM, RM>;
819
+ /**
820
+ * Time Complexity: O(n)
821
+ * Space Complexity: O(1)
822
+ *
823
+ */
824
+ countOccurrences(elementOrNode: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number;
823
825
  /**
824
826
  * Time Complexity: O(n)
825
827
  * Space Complexity: O(n)
@@ -784,13 +784,7 @@ class DoublyLinkedList extends base_1.IterableElementBase {
784
784
  * node was not found.
785
785
  */
786
786
  addBefore(existingElementOrNode, newElementOrNode) {
787
- let existingNode;
788
- if (existingElementOrNode instanceof DoublyLinkedListNode) {
789
- existingNode = existingElementOrNode;
790
- }
791
- else {
792
- existingNode = this.getNode(existingElementOrNode);
793
- }
787
+ const existingNode = this.getNode(existingElementOrNode);
794
788
  if (existingNode) {
795
789
  const newNode = this._ensureNode(newElementOrNode);
796
790
  newNode.prev = existingNode.prev;
@@ -824,13 +818,7 @@ class DoublyLinkedList extends base_1.IterableElementBase {
824
818
  * was not found in the linked list.
825
819
  */
826
820
  addAfter(existingElementOrNode, newElementOrNode) {
827
- let existingNode;
828
- if (existingElementOrNode instanceof DoublyLinkedListNode) {
829
- existingNode = existingElementOrNode;
830
- }
831
- else {
832
- existingNode = this.getNode(existingElementOrNode);
833
- }
821
+ const existingNode = this.getNode(existingElementOrNode);
834
822
  if (existingNode) {
835
823
  const newNode = this._ensureNode(newElementOrNode);
836
824
  newNode.next = existingNode.next;
@@ -936,17 +924,15 @@ class DoublyLinkedList extends base_1.IterableElementBase {
936
924
  * Time Complexity: O(n)
937
925
  * Space Complexity: O(1)
938
926
  *
939
- * The indexOf function in TypeScript returns the index of a specified element or node in a Doubly
940
- * Linked List.
941
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
942
- * `indexOf` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an
943
- * element of type `E`.
944
- * @returns The `indexOf` method is returning the index of the element or node in the doubly linked
945
- * list. If the element or node is found in the list, the method returns the index of that element or
946
- * node. If the element or node is not found in the list, the method returns -1.
927
+ * This function finds the index of a specified element, node, or predicate in a doubly linked list.
928
+ * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
929
+ * elementNodeOrPredicate - The `indexOf` method takes in a parameter `elementNodeOrPredicate`, which
930
+ * can be one of the following:
931
+ * @returns The `indexOf` method returns the index of the element in the doubly linked list that
932
+ * matches the provided element, node, or predicate. If no match is found, it returns -1.
947
933
  */
948
- indexOf(elementOrNode) {
949
- const predicate = this._ensurePredicate(elementOrNode);
934
+ indexOf(elementNodeOrPredicate) {
935
+ const predicate = this._ensurePredicate(elementNodeOrPredicate);
950
936
  let index = 0;
951
937
  let current = this.head;
952
938
  while (current) {
@@ -962,8 +948,6 @@ class DoublyLinkedList extends base_1.IterableElementBase {
962
948
  * Time Complexity: O(n)
963
949
  * Space Complexity: O(1)
964
950
  *
965
- */
966
- /**
967
951
  * This function retrieves an element from a doubly linked list based on a given element
968
952
  * node or predicate.
969
953
  * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
@@ -1122,6 +1106,23 @@ class DoublyLinkedList extends base_1.IterableElementBase {
1122
1106
  }
1123
1107
  return mappedList;
1124
1108
  }
1109
+ /**
1110
+ * Time Complexity: O(n)
1111
+ * Space Complexity: O(1)
1112
+ *
1113
+ */
1114
+ countOccurrences(elementOrNode) {
1115
+ const predicate = this._ensurePredicate(elementOrNode);
1116
+ let count = 0;
1117
+ let current = this.head;
1118
+ while (current) {
1119
+ if (predicate(current)) {
1120
+ count++;
1121
+ }
1122
+ current = current.next;
1123
+ }
1124
+ return count;
1125
+ }
1125
1126
  /**
1126
1127
  * Time Complexity: O(n)
1127
1128
  * Space Complexity: O(n)