heap-typed 1.53.2 → 1.53.4

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
@@ -39,61 +39,163 @@ Max Heap
39
39
 
40
40
  ### snippet
41
41
 
42
- #### TS
42
+ #### heap sort TS
43
43
 
44
44
  ```typescript
45
- import {MinHeap, MaxHeap} from 'data-structure-typed';
46
- // /* or if you prefer */ import {MinHeap, MaxHeap} from 'heap-typed';
47
-
48
- const minNumHeap = new MinHeap<number>([1, 6, 2, 0, 5]);
49
- minNumHeap.add(9);
50
- minNumHeap.has(1) // true
51
- minNumHeap.has(2) // true
52
- minNumHeap.poll() // 0
53
- minNumHeap.poll() // 1
54
- minNumHeap.peek() // 2
55
- minNumHeap.has(1); // false
56
- minNumHeap.has(2); // true
57
-
58
- const arrFromHeap = minNumHeap.toArray();
59
- arrFromHeap.length // 4
60
- arrFromHeap[0] // 2
61
- arrFromHeap[1] // 5
62
- arrFromHeap[2] // 9
63
- arrFromHeap[3] // 6
64
- minNumHeap.sort() // [2, 5, 6, 9]
65
-
66
- const maxHeap = new MaxHeap<{ keyA: string }>([], {comparator: (a, b) => b.keyA - a.keyA});
67
- const obj1 = {keyA: 'a1'}, obj6 = {keyA: 'a6'}, obj5 = {keyA: 'a5'}, obj2 = {keyA: 'a2'},
68
- obj0 = {keyA: 'a0'}, obj9 = {keyA: 'a9'};
69
-
70
- maxHeap.add(obj1);
71
- maxHeap.has(obj1) // true
72
- maxHeap.has(obj9) // false
73
- maxHeap.add(obj6);
74
- maxHeap.has(obj6) // true
75
- maxHeap.add(obj5);
76
- maxHeap.add(obj2);
77
- maxHeap.add(obj0);
78
- maxHeap.add(obj9);
79
- maxHeap.has(obj9) // true
80
-
81
- const peek9 = maxHeap.peek();
82
- console.log(peek9.keyA) // 'a9'
83
-
84
- const heapToArr = maxHeap.toArray();
85
- console.log(heapToArr.map(ele => ele?.keyA)); // ['a9', 'a2', 'a6', 'a1', 'a0', 'a5']
86
-
87
- const values = ['a9', 'a6', 'a5', 'a2', 'a1', 'a0'];
88
- let i = 0;
89
- while (maxHeap.size > 0) {
90
- const polled = maxHeap.poll();
91
- console.log(polled.keyA) // values[i]
92
- i++;
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
+ 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()) {
54
+ sorted.push(heap.poll()!); // Poll minimum element
55
+ }
56
+ return sorted;
57
+ }
58
+
59
+ console.log('Heap sorted:', heapSort([5, 3, 8, 4, 1, 2])); // [1, 2, 3, 4, 5, 8];
60
+
61
+ ```
62
+
63
+
64
+ #### top K problem TS
65
+
66
+ ```typescript
67
+ // Use Heap to resolve top K problem
68
+ function topKElements(arr: number[], k: number): number[] {
69
+ const heap = new Heap<number>([], {comparator: (a, b) => b - a}); // Max heap
70
+ arr.forEach((num) => {
71
+ heap.add(num);
72
+ if (heap.size > k) heap.poll(); // Keep the heap size at K
73
+ });
74
+ return heap.toArray();
75
+ }
76
+
77
+ const numbers = [10, 30, 20, 5, 15, 25];
78
+ console.log('Top K:', topKElements(numbers, 3)); // [15, 10, 5]
79
+ ```
80
+
81
+ #### real-time median TS
82
+
83
+ ```typescript
84
+ // Use Heap to maintain median value for real-time retrieval
85
+ class MedianFinder {
86
+ private low: MaxHeap<number>; // Max heap, stores the smaller half
87
+ private high: MinHeap<number>; // Min heap, stores the larger half
88
+
89
+ constructor() {
90
+ this.low = new MaxHeap<number>([]);
91
+ this.high = new MinHeap<number>([]);
92
+ }
93
+
94
+ addNum(num: number): void {
95
+ if (this.low.isEmpty() || num <= this.low.peek()!) this.low.add(num);
96
+ else this.high.add(num);
97
+
98
+ // Balance heaps
99
+ if (this.low.size > this.high.size + 1) this.high.add(this.low.poll()!);
100
+ else if (this.high.size > this.low.size) this.low.add(this.high.poll()!);
93
101
  }
102
+
103
+ findMedian(): number {
104
+ return this.low.peek()!;
105
+ }
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
+
121
+ #### load balance TS
122
+
123
+ ```typescript
124
+ // Use Heap for load balancing
125
+ 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);
128
+
129
+ for (let i = 0; i < servers; i++) {
130
+ serverHeap.add({ id: i, load: 0 });
131
+ }
132
+
133
+ requests.forEach(req => {
134
+ const server = serverHeap.poll()!;
135
+ serverLoads[server.id] += req;
136
+ server.load += req;
137
+ serverHeap.add(server); // The server after updating the load is re-entered into the heap
138
+ });
139
+
140
+ return serverLoads;
141
+ }
142
+
143
+ const requests = [5, 2, 8, 3, 7];
144
+ const serversLoads = loadBalance(requests, 3);
145
+ console.log('server loads: ', serversLoads); // [12, 8, 5]
146
+ ```
147
+ #### conventional operation TS
148
+
149
+ ```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
+ }
94
196
  ```
95
197
 
96
- #### JS
198
+ #### conventional operation JS
97
199
 
98
200
  ```javascript
99
201
  const {MinHeap, MaxHeap} = require('data-structure-typed');
@@ -17,6 +17,171 @@ import { IterableElementBase } from '../base';
17
17
  * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.
18
18
  * 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.
19
19
  * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prime's minimum-spanning tree algorithm, which use heaps to improve performance.
20
+ * @example
21
+ * // Use Heap to sort an array
22
+ * function heapSort(arr: number[]): number[] {
23
+ * const heap = new Heap<number>(arr, { comparator: (a, b) => a - b });
24
+ * const sorted: number[] = [];
25
+ * while (!heap.isEmpty()) {
26
+ * sorted.push(heap.poll()!); // Poll minimum element
27
+ * }
28
+ * return sorted;
29
+ * }
30
+ *
31
+ * const array = [5, 3, 8, 4, 1, 2];
32
+ * console.log(heapSort(array)); // [1, 2, 3, 4, 5, 8]
33
+ * @example
34
+ * // Use Heap to solve top k problems
35
+ * function topKElements(arr: number[], k: number): number[] {
36
+ * const heap = new Heap<number>([], { comparator: (a, b) => b - a }); // Max heap
37
+ * arr.forEach(num => {
38
+ * heap.add(num);
39
+ * if (heap.size > k) heap.poll(); // Keep the heap size at K
40
+ * });
41
+ * return heap.toArray();
42
+ * }
43
+ *
44
+ * const numbers = [10, 30, 20, 5, 15, 25];
45
+ * console.log(topKElements(numbers, 3)); // [15, 10, 5]
46
+ * @example
47
+ * // Use Heap to merge sorted sequences
48
+ * function mergeSortedSequences(sequences: number[][]): number[] {
49
+ * const heap = new Heap<{ value: number; seqIndex: number; itemIndex: number }>([], {
50
+ * comparator: (a, b) => a.value - b.value // Min heap
51
+ * });
52
+ *
53
+ * // Initialize heap
54
+ * sequences.forEach((seq, seqIndex) => {
55
+ * if (seq.length) {
56
+ * heap.add({ value: seq[0], seqIndex, itemIndex: 0 });
57
+ * }
58
+ * });
59
+ *
60
+ * const merged: number[] = [];
61
+ * while (!heap.isEmpty()) {
62
+ * const { value, seqIndex, itemIndex } = heap.poll()!;
63
+ * merged.push(value);
64
+ *
65
+ * if (itemIndex + 1 < sequences[seqIndex].length) {
66
+ * heap.add({
67
+ * value: sequences[seqIndex][itemIndex + 1],
68
+ * seqIndex,
69
+ * itemIndex: itemIndex + 1
70
+ * });
71
+ * }
72
+ * }
73
+ *
74
+ * return merged;
75
+ * }
76
+ *
77
+ * const sequences = [
78
+ * [1, 4, 7],
79
+ * [2, 5, 8],
80
+ * [3, 6, 9]
81
+ * ];
82
+ * console.log(mergeSortedSequences(sequences)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
83
+ * @example
84
+ * // Use Heap to dynamically maintain the median
85
+ * class MedianFinder {
86
+ * private low: MaxHeap<number>; // Max heap, stores the smaller half
87
+ * private high: MinHeap<number>; // Min heap, stores the larger half
88
+ *
89
+ * constructor() {
90
+ * this.low = new MaxHeap<number>([]);
91
+ * this.high = new MinHeap<number>([]);
92
+ * }
93
+ *
94
+ * addNum(num: number): void {
95
+ * if (this.low.isEmpty() || num <= this.low.peek()!) this.low.add(num);
96
+ * else this.high.add(num);
97
+ *
98
+ * // Balance heaps
99
+ * if (this.low.size > this.high.size + 1) this.high.add(this.low.poll()!);
100
+ * else if (this.high.size > this.low.size) this.low.add(this.high.poll()!);
101
+ * }
102
+ *
103
+ * findMedian(): number {
104
+ * if (this.low.size === this.high.size) return (this.low.peek()! + this.high.peek()!) / 2;
105
+ * return this.low.peek()!;
106
+ * }
107
+ * }
108
+ *
109
+ * const medianFinder = new MedianFinder();
110
+ * medianFinder.addNum(10);
111
+ * console.log(medianFinder.findMedian()); // 10
112
+ * medianFinder.addNum(20);
113
+ * console.log(medianFinder.findMedian()); // 15
114
+ * medianFinder.addNum(30);
115
+ * console.log(medianFinder.findMedian()); // 20
116
+ * medianFinder.addNum(40);
117
+ * console.log(medianFinder.findMedian()); // 25
118
+ * medianFinder.addNum(50);
119
+ * console.log(medianFinder.findMedian()); // 30
120
+ * @example
121
+ * // Use Heap for load balancing
122
+ * function loadBalance(requests: number[], servers: number): number[] {
123
+ * const serverHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // min heap
124
+ * const serverLoads = new Array(servers).fill(0);
125
+ *
126
+ * for (let i = 0; i < servers; i++) {
127
+ * serverHeap.add({ id: i, load: 0 });
128
+ * }
129
+ *
130
+ * requests.forEach(req => {
131
+ * const server = serverHeap.poll()!;
132
+ * serverLoads[server.id] += req;
133
+ * server.load += req;
134
+ * serverHeap.add(server); // The server after updating the load is re-entered into the heap
135
+ * });
136
+ *
137
+ * return serverLoads;
138
+ * }
139
+ *
140
+ * const requests = [5, 2, 8, 3, 7];
141
+ * console.log(loadBalance(requests, 3)); // [12, 8, 5]
142
+ * @example
143
+ * // Use Heap to schedule tasks
144
+ * type Task = [string, number];
145
+ *
146
+ * function scheduleTasks(tasks: Task[], machines: number): Map<number, Task[]> {
147
+ * const machineHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // Min heap
148
+ * const allocation = new Map<number, Task[]>();
149
+ *
150
+ * // Initialize the load on each machine
151
+ * for (let i = 0; i < machines; i++) {
152
+ * machineHeap.add({ id: i, load: 0 });
153
+ * allocation.set(i, []);
154
+ * }
155
+ *
156
+ * // Assign tasks
157
+ * tasks.forEach(([task, load]) => {
158
+ * const machine = machineHeap.poll()!;
159
+ * allocation.get(machine.id)!.push([task, load]);
160
+ * machine.load += load;
161
+ * machineHeap.add(machine); // The machine after updating the load is re-entered into the heap
162
+ * });
163
+ *
164
+ * return allocation;
165
+ * }
166
+ *
167
+ * const tasks: Task[] = [
168
+ * ['Task1', 3],
169
+ * ['Task2', 1],
170
+ * ['Task3', 2],
171
+ * ['Task4', 5],
172
+ * ['Task5', 4]
173
+ * ];
174
+ * const expectedMap = new Map<number, Task[]>();
175
+ * expectedMap.set(0, [
176
+ * ['Task1', 3],
177
+ * ['Task4', 5]
178
+ * ]);
179
+ * expectedMap.set(1, [
180
+ * ['Task2', 1],
181
+ * ['Task3', 2],
182
+ * ['Task5', 4]
183
+ * ]);
184
+ * console.log(scheduleTasks(tasks, 2)); // expectedMap
20
185
  */
21
186
  export declare class Heap<E = any, R = any> extends IterableElementBase<E, R, Heap<E, R>> {
22
187
  /**
@@ -19,6 +19,171 @@ const base_1 = require("../base");
19
19
  * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.
20
20
  * 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.
21
21
  * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prime's minimum-spanning tree algorithm, which use heaps to improve performance.
22
+ * @example
23
+ * // Use Heap to sort an array
24
+ * function heapSort(arr: number[]): number[] {
25
+ * const heap = new Heap<number>(arr, { comparator: (a, b) => a - b });
26
+ * const sorted: number[] = [];
27
+ * while (!heap.isEmpty()) {
28
+ * sorted.push(heap.poll()!); // Poll minimum element
29
+ * }
30
+ * return sorted;
31
+ * }
32
+ *
33
+ * const array = [5, 3, 8, 4, 1, 2];
34
+ * console.log(heapSort(array)); // [1, 2, 3, 4, 5, 8]
35
+ * @example
36
+ * // Use Heap to solve top k problems
37
+ * function topKElements(arr: number[], k: number): number[] {
38
+ * const heap = new Heap<number>([], { comparator: (a, b) => b - a }); // Max heap
39
+ * arr.forEach(num => {
40
+ * heap.add(num);
41
+ * if (heap.size > k) heap.poll(); // Keep the heap size at K
42
+ * });
43
+ * return heap.toArray();
44
+ * }
45
+ *
46
+ * const numbers = [10, 30, 20, 5, 15, 25];
47
+ * console.log(topKElements(numbers, 3)); // [15, 10, 5]
48
+ * @example
49
+ * // Use Heap to merge sorted sequences
50
+ * function mergeSortedSequences(sequences: number[][]): number[] {
51
+ * const heap = new Heap<{ value: number; seqIndex: number; itemIndex: number }>([], {
52
+ * comparator: (a, b) => a.value - b.value // Min heap
53
+ * });
54
+ *
55
+ * // Initialize heap
56
+ * sequences.forEach((seq, seqIndex) => {
57
+ * if (seq.length) {
58
+ * heap.add({ value: seq[0], seqIndex, itemIndex: 0 });
59
+ * }
60
+ * });
61
+ *
62
+ * const merged: number[] = [];
63
+ * while (!heap.isEmpty()) {
64
+ * const { value, seqIndex, itemIndex } = heap.poll()!;
65
+ * merged.push(value);
66
+ *
67
+ * if (itemIndex + 1 < sequences[seqIndex].length) {
68
+ * heap.add({
69
+ * value: sequences[seqIndex][itemIndex + 1],
70
+ * seqIndex,
71
+ * itemIndex: itemIndex + 1
72
+ * });
73
+ * }
74
+ * }
75
+ *
76
+ * return merged;
77
+ * }
78
+ *
79
+ * const sequences = [
80
+ * [1, 4, 7],
81
+ * [2, 5, 8],
82
+ * [3, 6, 9]
83
+ * ];
84
+ * console.log(mergeSortedSequences(sequences)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
85
+ * @example
86
+ * // Use Heap to dynamically maintain the median
87
+ * class MedianFinder {
88
+ * private low: MaxHeap<number>; // Max heap, stores the smaller half
89
+ * private high: MinHeap<number>; // Min heap, stores the larger half
90
+ *
91
+ * constructor() {
92
+ * this.low = new MaxHeap<number>([]);
93
+ * this.high = new MinHeap<number>([]);
94
+ * }
95
+ *
96
+ * addNum(num: number): void {
97
+ * if (this.low.isEmpty() || num <= this.low.peek()!) this.low.add(num);
98
+ * else this.high.add(num);
99
+ *
100
+ * // Balance heaps
101
+ * if (this.low.size > this.high.size + 1) this.high.add(this.low.poll()!);
102
+ * else if (this.high.size > this.low.size) this.low.add(this.high.poll()!);
103
+ * }
104
+ *
105
+ * findMedian(): number {
106
+ * if (this.low.size === this.high.size) return (this.low.peek()! + this.high.peek()!) / 2;
107
+ * return this.low.peek()!;
108
+ * }
109
+ * }
110
+ *
111
+ * const medianFinder = new MedianFinder();
112
+ * medianFinder.addNum(10);
113
+ * console.log(medianFinder.findMedian()); // 10
114
+ * medianFinder.addNum(20);
115
+ * console.log(medianFinder.findMedian()); // 15
116
+ * medianFinder.addNum(30);
117
+ * console.log(medianFinder.findMedian()); // 20
118
+ * medianFinder.addNum(40);
119
+ * console.log(medianFinder.findMedian()); // 25
120
+ * medianFinder.addNum(50);
121
+ * console.log(medianFinder.findMedian()); // 30
122
+ * @example
123
+ * // Use Heap for load balancing
124
+ * function loadBalance(requests: number[], servers: number): number[] {
125
+ * const serverHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // min heap
126
+ * const serverLoads = new Array(servers).fill(0);
127
+ *
128
+ * for (let i = 0; i < servers; i++) {
129
+ * serverHeap.add({ id: i, load: 0 });
130
+ * }
131
+ *
132
+ * requests.forEach(req => {
133
+ * const server = serverHeap.poll()!;
134
+ * serverLoads[server.id] += req;
135
+ * server.load += req;
136
+ * serverHeap.add(server); // The server after updating the load is re-entered into the heap
137
+ * });
138
+ *
139
+ * return serverLoads;
140
+ * }
141
+ *
142
+ * const requests = [5, 2, 8, 3, 7];
143
+ * console.log(loadBalance(requests, 3)); // [12, 8, 5]
144
+ * @example
145
+ * // Use Heap to schedule tasks
146
+ * type Task = [string, number];
147
+ *
148
+ * function scheduleTasks(tasks: Task[], machines: number): Map<number, Task[]> {
149
+ * const machineHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // Min heap
150
+ * const allocation = new Map<number, Task[]>();
151
+ *
152
+ * // Initialize the load on each machine
153
+ * for (let i = 0; i < machines; i++) {
154
+ * machineHeap.add({ id: i, load: 0 });
155
+ * allocation.set(i, []);
156
+ * }
157
+ *
158
+ * // Assign tasks
159
+ * tasks.forEach(([task, load]) => {
160
+ * const machine = machineHeap.poll()!;
161
+ * allocation.get(machine.id)!.push([task, load]);
162
+ * machine.load += load;
163
+ * machineHeap.add(machine); // The machine after updating the load is re-entered into the heap
164
+ * });
165
+ *
166
+ * return allocation;
167
+ * }
168
+ *
169
+ * const tasks: Task[] = [
170
+ * ['Task1', 3],
171
+ * ['Task2', 1],
172
+ * ['Task3', 2],
173
+ * ['Task4', 5],
174
+ * ['Task5', 4]
175
+ * ];
176
+ * const expectedMap = new Map<number, Task[]>();
177
+ * expectedMap.set(0, [
178
+ * ['Task1', 3],
179
+ * ['Task4', 5]
180
+ * ]);
181
+ * expectedMap.set(1, [
182
+ * ['Task2', 1],
183
+ * ['Task3', 2],
184
+ * ['Task5', 4]
185
+ * ]);
186
+ * console.log(scheduleTasks(tasks, 2)); // expectedMap
22
187
  */
23
188
  class Heap extends base_1.IterableElementBase {
24
189
  /**