deque-typed 1.49.3 → 1.49.5
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/dist/data-structures/base/iterable-base.d.ts +1 -1
- package/dist/data-structures/binary-tree/binary-tree.d.ts +2 -14
- package/dist/data-structures/binary-tree/binary-tree.js +19 -49
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +0 -16
- package/dist/data-structures/binary-tree/tree-multimap.js +1 -43
- package/dist/data-structures/graph/abstract-graph.d.ts +2 -11
- package/dist/data-structures/graph/abstract-graph.js +3 -19
- package/dist/data-structures/graph/directed-graph.js +4 -0
- package/dist/data-structures/hash/hash-map.d.ts +1 -1
- package/dist/data-structures/hash/hash-map.js +2 -2
- package/dist/data-structures/heap/heap.js +2 -3
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +2 -2
- package/dist/data-structures/matrix/index.d.ts +0 -2
- package/dist/data-structures/matrix/index.js +0 -2
- package/dist/data-structures/matrix/matrix.d.ts +128 -10
- package/dist/data-structures/matrix/matrix.js +400 -15
- package/dist/data-structures/queue/deque.d.ts +2 -2
- package/dist/data-structures/queue/deque.js +5 -7
- package/dist/data-structures/queue/queue.d.ts +1 -1
- package/dist/types/data-structures/base/base.d.ts +1 -1
- package/dist/types/data-structures/heap/heap.d.ts +1 -1
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +1 -1
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.js +6 -1
- package/package.json +2 -2
- package/src/data-structures/base/index.ts +1 -1
- package/src/data-structures/base/iterable-base.ts +7 -10
- package/src/data-structures/binary-tree/avl-tree.ts +15 -8
- package/src/data-structures/binary-tree/binary-tree.ts +57 -74
- package/src/data-structures/binary-tree/bst.ts +16 -13
- package/src/data-structures/binary-tree/rb-tree.ts +16 -10
- package/src/data-structures/binary-tree/tree-multimap.ts +11 -48
- package/src/data-structures/graph/abstract-graph.ts +14 -24
- package/src/data-structures/graph/directed-graph.ts +8 -6
- package/src/data-structures/graph/map-graph.ts +6 -1
- package/src/data-structures/graph/undirected-graph.ts +4 -7
- package/src/data-structures/hash/hash-map.ts +18 -16
- package/src/data-structures/heap/heap.ts +7 -10
- package/src/data-structures/heap/max-heap.ts +2 -1
- package/src/data-structures/heap/min-heap.ts +2 -1
- package/src/data-structures/linked-list/singly-linked-list.ts +3 -5
- package/src/data-structures/matrix/index.ts +0 -2
- package/src/data-structures/matrix/matrix.ts +442 -13
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -10
- package/src/data-structures/queue/deque.ts +18 -39
- package/src/data-structures/queue/queue.ts +1 -1
- package/src/interfaces/binary-tree.ts +7 -2
- package/src/types/common.ts +4 -4
- package/src/types/data-structures/base/base.ts +14 -3
- package/src/types/data-structures/base/index.ts +1 -1
- package/src/types/data-structures/graph/abstract-graph.ts +4 -2
- package/src/types/data-structures/hash/hash-map.ts +3 -3
- package/src/types/data-structures/heap/heap.ts +2 -2
- package/src/types/data-structures/priority-queue/priority-queue.ts +2 -2
- package/src/utils/utils.ts +7 -1
- package/dist/data-structures/matrix/matrix2d.d.ts +0 -107
- package/dist/data-structures/matrix/matrix2d.js +0 -199
- package/dist/data-structures/matrix/vector2d.d.ts +0 -200
- package/dist/data-structures/matrix/vector2d.js +0 -290
- package/src/data-structures/matrix/matrix2d.ts +0 -211
- package/src/data-structures/matrix/vector2d.ts +0 -315
|
@@ -5,23 +5,452 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
// todo need to be improved
|
|
9
|
-
export class MatrixNTI2D<V = any> {
|
|
10
|
-
protected readonly _matrix: Array<Array<V>>;
|
|
11
8
|
|
|
9
|
+
export class Matrix {
|
|
12
10
|
/**
|
|
13
|
-
* The constructor
|
|
14
|
-
*
|
|
15
|
-
* @param
|
|
11
|
+
* The constructor function initializes a matrix object with the provided data and options, or with
|
|
12
|
+
* default values if no options are provided.
|
|
13
|
+
* @param {number[][]} data - A 2D array of numbers representing the data for the matrix.
|
|
14
|
+
* @param [options] - The `options` parameter is an optional object that can contain the following
|
|
15
|
+
* properties:
|
|
16
16
|
*/
|
|
17
|
-
constructor(
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
constructor(
|
|
18
|
+
data: number[][],
|
|
19
|
+
options?: {
|
|
20
|
+
rows?: number;
|
|
21
|
+
cols?: number;
|
|
22
|
+
addFn?: (a: number, b: number) => any;
|
|
23
|
+
subtractFn?: (a: number, b: number) => any;
|
|
24
|
+
multiplyFn?: (a: number, b: number) => any;
|
|
25
|
+
}
|
|
26
|
+
) {
|
|
27
|
+
if (options) {
|
|
28
|
+
const { rows, cols, addFn, subtractFn, multiplyFn } = options;
|
|
29
|
+
if (typeof rows === 'number' && rows > 0) this._rows = rows;
|
|
30
|
+
else this._rows = data.length;
|
|
31
|
+
if (typeof cols === 'number' && cols > 0) this._cols = cols;
|
|
32
|
+
else this._cols = data[0]?.length || 0;
|
|
33
|
+
if (addFn) this._addFn = addFn;
|
|
34
|
+
if (subtractFn) this._subtractFn = subtractFn;
|
|
35
|
+
if (multiplyFn) this._multiplyFn = multiplyFn;
|
|
36
|
+
} else {
|
|
37
|
+
this._rows = data.length;
|
|
38
|
+
this._cols = data[0]?.length ?? 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (data.length > 0) {
|
|
42
|
+
this._data = data;
|
|
43
|
+
} else {
|
|
44
|
+
this._data = [];
|
|
45
|
+
for (let i = 0; i < this.rows; i++) {
|
|
46
|
+
this._data[i] = new Array(this.cols).fill(0);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
protected _rows: number = 0;
|
|
52
|
+
|
|
53
|
+
get rows(): number {
|
|
54
|
+
return this._rows;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
protected _cols: number = 0;
|
|
58
|
+
|
|
59
|
+
get cols(): number {
|
|
60
|
+
return this._cols;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected _data: number[][];
|
|
64
|
+
|
|
65
|
+
get data(): number[][] {
|
|
66
|
+
return this._data;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get addFn() {
|
|
70
|
+
return this._addFn;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get subtractFn() {
|
|
74
|
+
return this._subtractFn;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get multiplyFn() {
|
|
78
|
+
return this._multiplyFn;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The `get` function returns the value at the specified row and column index if it is a valid index.
|
|
83
|
+
* @param {number} row - The `row` parameter represents the row index of the element you want to
|
|
84
|
+
* retrieve from the data array.
|
|
85
|
+
* @param {number} col - The parameter "col" represents the column number of the element you want to
|
|
86
|
+
* retrieve from the data array.
|
|
87
|
+
* @returns The `get` function returns a number if the provided row and column indices are valid.
|
|
88
|
+
* Otherwise, it returns `undefined`.
|
|
89
|
+
*/
|
|
90
|
+
get(row: number, col: number): number | undefined {
|
|
91
|
+
if (this.isValidIndex(row, col)) {
|
|
92
|
+
return this.data[row][col];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The set function updates the value at a specified row and column in a two-dimensional array.
|
|
98
|
+
* @param {number} row - The "row" parameter represents the row index of the element in a
|
|
99
|
+
* two-dimensional array or matrix. It specifies the row where the value will be set.
|
|
100
|
+
* @param {number} col - The "col" parameter represents the column index of the element in a
|
|
101
|
+
* two-dimensional array.
|
|
102
|
+
* @param {number} value - The value parameter represents the number that you want to set at the
|
|
103
|
+
* specified row and column in the data array.
|
|
104
|
+
* @returns a boolean value. It returns true if the index (row, col) is valid and the value is
|
|
105
|
+
* successfully set in the data array. It returns false if the index is invalid and the value is not
|
|
106
|
+
* set.
|
|
107
|
+
*/
|
|
108
|
+
set(row: number, col: number, value: number): boolean {
|
|
109
|
+
if (this.isValidIndex(row, col)) {
|
|
110
|
+
this.data[row][col] = value;
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
20
114
|
}
|
|
21
115
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
116
|
+
/**
|
|
117
|
+
* The function checks if the dimensions of the given matrix match the dimensions of the current
|
|
118
|
+
* matrix.
|
|
119
|
+
* @param {Matrix} matrix - The parameter `matrix` is of type `Matrix`.
|
|
120
|
+
* @returns a boolean value.
|
|
121
|
+
*/
|
|
122
|
+
isMatchForCalculate(matrix: Matrix): boolean {
|
|
123
|
+
return this.rows === matrix.rows && this.cols === matrix.cols;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The `add` function adds two matrices together, returning a new matrix with the result.
|
|
128
|
+
* @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.
|
|
129
|
+
* @returns The `add` method returns a new `Matrix` object that represents the result of adding the
|
|
130
|
+
* current matrix with the provided `matrix` parameter.
|
|
131
|
+
*/
|
|
132
|
+
add(matrix: Matrix): Matrix | undefined {
|
|
133
|
+
if (!this.isMatchForCalculate(matrix)) {
|
|
134
|
+
throw new Error('Matrix dimensions must match for addition.');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const resultData: number[][] = [];
|
|
138
|
+
for (let i = 0; i < this.rows; i++) {
|
|
139
|
+
resultData[i] = [];
|
|
140
|
+
for (let j = 0; j < this.cols; j++) {
|
|
141
|
+
const a = this.get(i, j),
|
|
142
|
+
b = matrix.get(i, j);
|
|
143
|
+
if (a !== undefined && b !== undefined) {
|
|
144
|
+
const added = this._addFn(a, b);
|
|
145
|
+
if (added) {
|
|
146
|
+
resultData[i][j] = added;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return new Matrix(resultData, {
|
|
153
|
+
rows: this.rows,
|
|
154
|
+
cols: this.cols,
|
|
155
|
+
addFn: this.addFn,
|
|
156
|
+
subtractFn: this.subtractFn,
|
|
157
|
+
multiplyFn: this.multiplyFn
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The `subtract` function performs element-wise subtraction between two matrices and returns a new
|
|
163
|
+
* matrix with the result.
|
|
164
|
+
* @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class. It
|
|
165
|
+
* represents the matrix that you want to subtract from the current matrix.
|
|
166
|
+
* @returns a new Matrix object with the result of the subtraction operation.
|
|
167
|
+
*/
|
|
168
|
+
subtract(matrix: Matrix): Matrix | undefined {
|
|
169
|
+
if (!this.isMatchForCalculate(matrix)) {
|
|
170
|
+
throw new Error('Matrix dimensions must match for subtraction.');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const resultData: number[][] = [];
|
|
174
|
+
for (let i = 0; i < this.rows; i++) {
|
|
175
|
+
resultData[i] = [];
|
|
176
|
+
for (let j = 0; j < this.cols; j++) {
|
|
177
|
+
const a = this.get(i, j),
|
|
178
|
+
b = matrix.get(i, j);
|
|
179
|
+
if (a !== undefined && b !== undefined) {
|
|
180
|
+
const subtracted = this._subtractFn(a, b);
|
|
181
|
+
if (subtracted) {
|
|
182
|
+
resultData[i][j] = subtracted;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return new Matrix(resultData, {
|
|
189
|
+
rows: this.rows,
|
|
190
|
+
cols: this.cols,
|
|
191
|
+
addFn: this.addFn,
|
|
192
|
+
subtractFn: this.subtractFn,
|
|
193
|
+
multiplyFn: this.multiplyFn
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The `multiply` function performs matrix multiplication between two matrices and returns the result
|
|
199
|
+
* as a new matrix.
|
|
200
|
+
* @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.
|
|
201
|
+
* @returns a new Matrix object.
|
|
202
|
+
*/
|
|
203
|
+
multiply(matrix: Matrix): Matrix | undefined {
|
|
204
|
+
if (this.cols !== matrix.rows) {
|
|
205
|
+
throw new Error('Matrix dimensions must be compatible for multiplication (A.cols = B.rows).');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const resultData: number[][] = [];
|
|
209
|
+
for (let i = 0; i < this.rows; i++) {
|
|
210
|
+
resultData[i] = [];
|
|
211
|
+
for (let j = 0; j < matrix.cols; j++) {
|
|
212
|
+
let sum: number | undefined;
|
|
213
|
+
for (let k = 0; k < this.cols; k++) {
|
|
214
|
+
const a = this.get(i, k),
|
|
215
|
+
b = matrix.get(k, j);
|
|
216
|
+
if (a !== undefined && b !== undefined) {
|
|
217
|
+
const multiplied = this.multiplyFn(a, b);
|
|
218
|
+
if (multiplied !== undefined) {
|
|
219
|
+
sum = this.addFn(sum, multiplied);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (sum !== undefined) resultData[i][j] = sum;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return new Matrix(resultData, {
|
|
228
|
+
rows: this.rows,
|
|
229
|
+
cols: matrix.cols,
|
|
230
|
+
addFn: this.addFn,
|
|
231
|
+
subtractFn: this.subtractFn,
|
|
232
|
+
multiplyFn: this.multiplyFn
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* The transpose function takes a matrix and returns a new matrix that is the transpose of the
|
|
238
|
+
* original matrix.
|
|
239
|
+
* @returns The transpose() function returns a new Matrix object with the transposed data.
|
|
240
|
+
*/
|
|
241
|
+
transpose(): Matrix {
|
|
242
|
+
if (this.data.some(row => row.length !== this.rows)) {
|
|
243
|
+
throw new Error('Matrix must be rectangular for transposition.');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const resultData: number[][] = [];
|
|
247
|
+
|
|
248
|
+
for (let j = 0; j < this.cols; j++) {
|
|
249
|
+
resultData[j] = [];
|
|
250
|
+
for (let i = 0; i < this.rows; i++) {
|
|
251
|
+
const trans = this.get(i, j);
|
|
252
|
+
if (trans !== undefined) resultData[j][i] = trans;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return new Matrix(resultData, {
|
|
257
|
+
rows: this.cols,
|
|
258
|
+
cols: this.rows,
|
|
259
|
+
addFn: this.addFn,
|
|
260
|
+
subtractFn: this.subtractFn,
|
|
261
|
+
multiplyFn: this.multiplyFn
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* The `inverse` function calculates the inverse of a square matrix using Gaussian elimination.
|
|
267
|
+
* @returns a Matrix object, which represents the inverse of the original matrix.
|
|
268
|
+
*/
|
|
269
|
+
inverse(): Matrix | undefined {
|
|
270
|
+
// Check if the matrix is square
|
|
271
|
+
if (this.rows !== this.cols) {
|
|
272
|
+
throw new Error('Matrix must be square for inversion.');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Create an augmented matrix [this | I]
|
|
276
|
+
const augmentedMatrixData: number[][] = [];
|
|
277
|
+
for (let i = 0; i < this.rows; i++) {
|
|
278
|
+
augmentedMatrixData[i] = this.data[i].slice(); // Copy the original matrix
|
|
279
|
+
for (let j = 0; j < this.cols; j++) {
|
|
280
|
+
augmentedMatrixData[i][this.cols + j] = i === j ? 1 : 0; // Append the identity matrix
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const augmentedMatrix = new Matrix(augmentedMatrixData, {
|
|
285
|
+
rows: this.rows,
|
|
286
|
+
cols: this.cols * 2,
|
|
287
|
+
addFn: this.addFn,
|
|
288
|
+
subtractFn: this.subtractFn,
|
|
289
|
+
multiplyFn: this.multiplyFn
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// Apply Gaussian elimination to transform the left half into the identity matrix
|
|
293
|
+
for (let i = 0; i < this.rows; i++) {
|
|
294
|
+
// Find pivot
|
|
295
|
+
let pivotRow = i;
|
|
296
|
+
while (pivotRow < this.rows && augmentedMatrix.get(pivotRow, i) === 0) {
|
|
297
|
+
pivotRow++;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (pivotRow === this.rows) {
|
|
301
|
+
// Matrix is singular, and its inverse does not exist
|
|
302
|
+
throw new Error('Matrix is singular, and its inverse does not exist.');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Swap rows to make the pivot the current row
|
|
306
|
+
augmentedMatrix._swapRows(i, pivotRow);
|
|
307
|
+
|
|
308
|
+
// Scale the pivot row to make the pivot element 1
|
|
309
|
+
const pivotElement = augmentedMatrix.get(i, i) ?? 1;
|
|
310
|
+
|
|
311
|
+
if (pivotElement === 0) {
|
|
312
|
+
// Handle division by zero
|
|
313
|
+
throw new Error('Matrix is singular, and its inverse does not exist (division by zero).');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
augmentedMatrix._scaleRow(i, 1 / pivotElement);
|
|
317
|
+
|
|
318
|
+
// Eliminate other rows to make elements in the current column zero
|
|
319
|
+
for (let j = 0; j < this.rows; j++) {
|
|
320
|
+
if (j !== i) {
|
|
321
|
+
let factor = augmentedMatrix.get(j, i);
|
|
322
|
+
if (factor === undefined) factor = 0;
|
|
323
|
+
|
|
324
|
+
augmentedMatrix._addScaledRow(j, i, -factor);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Extract the right half of the augmented matrix as the inverse
|
|
330
|
+
const inverseData: number[][] = [];
|
|
331
|
+
for (let i = 0; i < this.rows; i++) {
|
|
332
|
+
inverseData[i] = augmentedMatrix.data[i].slice(this.cols);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return new Matrix(inverseData, {
|
|
336
|
+
rows: this.rows,
|
|
337
|
+
cols: this.cols,
|
|
338
|
+
addFn: this.addFn,
|
|
339
|
+
subtractFn: this.subtractFn,
|
|
340
|
+
multiplyFn: this.multiplyFn
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* The dot function calculates the dot product of two matrices and returns a new matrix.
|
|
346
|
+
* @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.
|
|
347
|
+
* @returns a new Matrix object.
|
|
348
|
+
*/
|
|
349
|
+
dot(matrix: Matrix): Matrix | undefined {
|
|
350
|
+
if (this.cols !== matrix.rows) {
|
|
351
|
+
throw new Error(
|
|
352
|
+
'Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product.'
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const resultData: number[][] = [];
|
|
357
|
+
for (let i = 0; i < this.rows; i++) {
|
|
358
|
+
resultData[i] = [];
|
|
359
|
+
for (let j = 0; j < matrix.cols; j++) {
|
|
360
|
+
let sum: number | undefined;
|
|
361
|
+
for (let k = 0; k < this.cols; k++) {
|
|
362
|
+
const a = this.get(i, k),
|
|
363
|
+
b = matrix.get(k, j);
|
|
364
|
+
if (a !== undefined && b !== undefined) {
|
|
365
|
+
const multiplied = this.multiplyFn(a, b);
|
|
366
|
+
if (multiplied !== undefined) {
|
|
367
|
+
sum = this.addFn(sum, multiplied);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (sum !== undefined) resultData[i][j] = sum;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return new Matrix(resultData, {
|
|
376
|
+
rows: this.rows,
|
|
377
|
+
cols: matrix.cols,
|
|
378
|
+
addFn: this.addFn,
|
|
379
|
+
subtractFn: this.subtractFn,
|
|
380
|
+
multiplyFn: this.multiplyFn
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
protected _addFn(a: number | undefined, b: number): number | undefined {
|
|
385
|
+
if (a === undefined) return b;
|
|
386
|
+
return a + b;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
protected _subtractFn(a: number, b: number) {
|
|
390
|
+
return a - b;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
protected _multiplyFn(a: number, b: number) {
|
|
394
|
+
return a * b;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* The function checks if a given row and column index is valid within a specified range.
|
|
399
|
+
* @param {number} row - The `row` parameter represents the row index of a two-dimensional array or
|
|
400
|
+
* matrix. It is a number that indicates the specific row in the matrix.
|
|
401
|
+
* @param {number} col - The "col" parameter represents the column index in a two-dimensional array
|
|
402
|
+
* or grid. It is used to check if the given column index is valid within the bounds of the grid.
|
|
403
|
+
* @returns A boolean value is being returned.
|
|
404
|
+
*/
|
|
405
|
+
protected isValidIndex(row: number, col: number): boolean {
|
|
406
|
+
return row >= 0 && row < this.rows && col >= 0 && col < this.cols;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* The function `_swapRows` swaps the positions of two rows in an array.
|
|
411
|
+
* @param {number} row1 - The `row1` parameter is the index of the first row that you want to swap.
|
|
412
|
+
* @param {number} row2 - The `row2` parameter is the index of the second row that you want to swap
|
|
413
|
+
* with the first row.
|
|
414
|
+
*/
|
|
415
|
+
protected _swapRows(row1: number, row2: number): void {
|
|
416
|
+
const temp = this.data[row1];
|
|
417
|
+
this.data[row1] = this.data[row2];
|
|
418
|
+
this.data[row2] = temp;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* The function scales a specific row in a matrix by a given scalar value.
|
|
423
|
+
* @param {number} row - The `row` parameter represents the index of the row in the matrix that you
|
|
424
|
+
* want to scale. It is a number that indicates the position of the row within the matrix.
|
|
425
|
+
* @param {number} scalar - The scalar parameter is a number that is used to multiply each element in
|
|
426
|
+
* a specific row of a matrix.
|
|
427
|
+
*/
|
|
428
|
+
protected _scaleRow(row: number, scalar: number): void {
|
|
429
|
+
for (let j = 0; j < this.cols; j++) {
|
|
430
|
+
let multiplied = this.multiplyFn(this.data[row][j], scalar);
|
|
431
|
+
if (multiplied === undefined) multiplied = 0;
|
|
432
|
+
this.data[row][j] = multiplied;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* The function `_addScaledRow` multiplies a row in a matrix by a scalar value and adds it to another
|
|
438
|
+
* row.
|
|
439
|
+
* @param {number} targetRow - The targetRow parameter represents the index of the row in which the
|
|
440
|
+
* scaled values will be added.
|
|
441
|
+
* @param {number} sourceRow - The sourceRow parameter represents the index of the row from which the
|
|
442
|
+
* values will be scaled and added to the targetRow.
|
|
443
|
+
* @param {number} scalar - The scalar parameter is a number that is used to scale the values in the
|
|
444
|
+
* source row before adding them to the target row.
|
|
445
|
+
*/
|
|
446
|
+
protected _addScaledRow(targetRow: number, sourceRow: number, scalar: number): void {
|
|
447
|
+
for (let j = 0; j < this.cols; j++) {
|
|
448
|
+
let multiplied = this.multiplyFn(this.data[sourceRow][j], scalar);
|
|
449
|
+
if (multiplied === undefined) multiplied = 0;
|
|
450
|
+
const scaledValue = multiplied;
|
|
451
|
+
let added = this.addFn(this.data[targetRow][j], scaledValue);
|
|
452
|
+
if (added === undefined) added = 0;
|
|
453
|
+
this.data[targetRow][j] = added;
|
|
454
|
+
}
|
|
26
455
|
}
|
|
27
456
|
}
|
|
@@ -9,16 +9,17 @@ import type { PriorityQueueOptions } from '../../types';
|
|
|
9
9
|
import { PriorityQueue } from './priority-queue';
|
|
10
10
|
|
|
11
11
|
export class MinPriorityQueue<E = any> extends PriorityQueue<E> {
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
constructor(
|
|
13
|
+
elements?: Iterable<E>,
|
|
14
|
+
options: PriorityQueueOptions<E> = {
|
|
15
|
+
comparator: (a: E, b: E) => {
|
|
16
|
+
if (!(typeof a === 'number' && typeof b === 'number')) {
|
|
17
|
+
throw new Error('The a, b params of compare function must be number');
|
|
18
|
+
} else {
|
|
19
|
+
return a - b;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
22
23
|
) {
|
|
23
24
|
super(elements, options);
|
|
24
25
|
}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import type { ElementCallback, IterableWithSizeOrLength } from
|
|
9
|
-
import { IterableElementBase } from
|
|
10
|
-
import { calcMinUnitsRequired, rangeCheck } from
|
|
8
|
+
import type { ElementCallback, IterableWithSizeOrLength } from '../../types';
|
|
9
|
+
import { IterableElementBase } from '../base';
|
|
10
|
+
import { calcMinUnitsRequired, rangeCheck } from '../../utils';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* 1. Operations at Both Ends: Supports adding and removing elements at both the front and back of the queue. This allows it to be used as a stack (last in, first out) and a queue (first in, first out).
|
|
@@ -33,13 +33,15 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
33
33
|
* @param bucketSize - The `bucketSize` parameter is the maximum number of elements that can be
|
|
34
34
|
* stored in each bucket. It determines the size of each bucket in the data structure.
|
|
35
35
|
*/
|
|
36
|
-
constructor(elements: IterableWithSizeOrLength<E> = [], bucketSize =
|
|
36
|
+
constructor(elements: IterableWithSizeOrLength<E> = [], bucketSize = 1 << 12) {
|
|
37
37
|
super();
|
|
38
38
|
let _size: number;
|
|
39
39
|
if ('length' in elements) {
|
|
40
|
-
if (elements.length instanceof Function) _size = elements.length();
|
|
40
|
+
if (elements.length instanceof Function) _size = elements.length();
|
|
41
|
+
else _size = elements.length;
|
|
41
42
|
} else {
|
|
42
|
-
if (elements.size instanceof Function) _size = elements.size();
|
|
43
|
+
if (elements.size instanceof Function) _size = elements.size();
|
|
44
|
+
else _size = elements.size;
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
this._bucketSize = bucketSize;
|
|
@@ -49,7 +51,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
49
51
|
}
|
|
50
52
|
const needBucketNum = calcMinUnitsRequired(_size, this._bucketSize);
|
|
51
53
|
this._bucketFirst = this._bucketLast = (this._bucketCount >> 1) - (needBucketNum >> 1);
|
|
52
|
-
this._firstInBucket = this._lastInBucket = (this._bucketSize - _size % this._bucketSize) >> 1;
|
|
54
|
+
this._firstInBucket = this._lastInBucket = (this._bucketSize - (_size % this._bucketSize)) >> 1;
|
|
53
55
|
|
|
54
56
|
for (const element of elements) {
|
|
55
57
|
this.push(element);
|
|
@@ -108,10 +110,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
108
110
|
this._bucketLast = 0;
|
|
109
111
|
this._lastInBucket = 0;
|
|
110
112
|
}
|
|
111
|
-
if (
|
|
112
|
-
this._bucketLast === this._bucketFirst &&
|
|
113
|
-
this._lastInBucket === this._firstInBucket
|
|
114
|
-
) this._reallocate();
|
|
113
|
+
if (this._bucketLast === this._bucketFirst && this._lastInBucket === this._firstInBucket) this._reallocate();
|
|
115
114
|
}
|
|
116
115
|
this._size += 1;
|
|
117
116
|
this._buckets[this._bucketLast][this._lastInBucket] = element;
|
|
@@ -175,10 +174,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
175
174
|
this._bucketFirst = this._bucketCount - 1;
|
|
176
175
|
this._firstInBucket = this._bucketSize - 1;
|
|
177
176
|
}
|
|
178
|
-
if (
|
|
179
|
-
this._bucketFirst === this._bucketLast &&
|
|
180
|
-
this._firstInBucket === this._lastInBucket
|
|
181
|
-
) this._reallocate();
|
|
177
|
+
if (this._bucketFirst === this._bucketLast && this._firstInBucket === this._lastInBucket) this._reallocate();
|
|
182
178
|
}
|
|
183
179
|
this._size += 1;
|
|
184
180
|
this._buckets[this._bucketFirst][this._firstInBucket] = element;
|
|
@@ -260,7 +256,6 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
260
256
|
}
|
|
261
257
|
}
|
|
262
258
|
|
|
263
|
-
|
|
264
259
|
/**
|
|
265
260
|
* Time Complexity: O(1)
|
|
266
261
|
* Space Complexity: O(1)
|
|
@@ -278,14 +273,10 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
278
273
|
*/
|
|
279
274
|
getAt(pos: number): E {
|
|
280
275
|
rangeCheck(pos, 0, this.size - 1);
|
|
281
|
-
const {
|
|
282
|
-
bucketIndex,
|
|
283
|
-
indexInBucket
|
|
284
|
-
} = this._getBucketAndPosition(pos);
|
|
276
|
+
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
|
285
277
|
return this._buckets[bucketIndex][indexInBucket]!;
|
|
286
278
|
}
|
|
287
279
|
|
|
288
|
-
|
|
289
280
|
/**
|
|
290
281
|
* Time Complexity: O(1)
|
|
291
282
|
* Space Complexity: O(1)
|
|
@@ -303,10 +294,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
303
294
|
*/
|
|
304
295
|
setAt(pos: number, element: E): boolean {
|
|
305
296
|
rangeCheck(pos, 0, this.size - 1);
|
|
306
|
-
const {
|
|
307
|
-
bucketIndex,
|
|
308
|
-
indexInBucket
|
|
309
|
-
} = this._getBucketAndPosition(pos);
|
|
297
|
+
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
|
310
298
|
this._buckets[bucketIndex][indexInBucket] = element;
|
|
311
299
|
return true;
|
|
312
300
|
}
|
|
@@ -370,10 +358,7 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
370
358
|
this.clear();
|
|
371
359
|
return 0;
|
|
372
360
|
}
|
|
373
|
-
const {
|
|
374
|
-
bucketIndex,
|
|
375
|
-
indexInBucket
|
|
376
|
-
} = this._getBucketAndPosition(pos);
|
|
361
|
+
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
|
|
377
362
|
this._bucketLast = bucketIndex;
|
|
378
363
|
this._lastInBucket = indexInBucket;
|
|
379
364
|
this._size = pos + 1;
|
|
@@ -402,15 +387,9 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
402
387
|
else if (pos === this.size - 1) this.pop();
|
|
403
388
|
else {
|
|
404
389
|
const length = this.size - 1;
|
|
405
|
-
let {
|
|
406
|
-
bucketIndex: curBucket,
|
|
407
|
-
indexInBucket: curPointer
|
|
408
|
-
} = this._getBucketAndPosition(pos);
|
|
390
|
+
let { bucketIndex: curBucket, indexInBucket: curPointer } = this._getBucketAndPosition(pos);
|
|
409
391
|
for (let i = pos; i < length; ++i) {
|
|
410
|
-
const {
|
|
411
|
-
bucketIndex: nextBucket,
|
|
412
|
-
indexInBucket: nextPointer
|
|
413
|
-
} = this._getBucketAndPosition(pos + 1);
|
|
392
|
+
const { bucketIndex: nextBucket, indexInBucket: nextPointer } = this._getBucketAndPosition(pos + 1);
|
|
414
393
|
this._buckets[curBucket][curPointer] = this._buckets[nextBucket][nextPointer];
|
|
415
394
|
curBucket = nextBucket;
|
|
416
395
|
curPointer = nextPointer;
|
|
@@ -827,11 +806,11 @@ export class Deque<E> extends IterableElementBase<E> {
|
|
|
827
806
|
bucketIndex -= this._bucketCount;
|
|
828
807
|
}
|
|
829
808
|
|
|
830
|
-
indexInBucket = (overallIndex + 1) % this._bucketSize - 1;
|
|
809
|
+
indexInBucket = ((overallIndex + 1) % this._bucketSize) - 1;
|
|
831
810
|
if (indexInBucket < 0) {
|
|
832
811
|
indexInBucket = this._bucketSize - 1;
|
|
833
812
|
}
|
|
834
813
|
|
|
835
814
|
return { bucketIndex, indexInBucket };
|
|
836
815
|
}
|
|
837
|
-
}
|
|
816
|
+
}
|
|
@@ -5,10 +5,15 @@ import {
|
|
|
5
5
|
BinaryTreeNodeNested,
|
|
6
6
|
BinaryTreeOptions,
|
|
7
7
|
BTNCallback,
|
|
8
|
-
BTNExemplar
|
|
8
|
+
BTNExemplar
|
|
9
9
|
} from '../types';
|
|
10
10
|
|
|
11
|
-
export interface IBinaryTree<
|
|
11
|
+
export interface IBinaryTree<
|
|
12
|
+
K = number,
|
|
13
|
+
V = any,
|
|
14
|
+
N extends BinaryTreeNode<K, V, N> = BinaryTreeNodeNested<K, V>,
|
|
15
|
+
TREE extends BinaryTree<K, V, N, TREE> = BinaryTreeNested<K, V, N>
|
|
16
|
+
> {
|
|
12
17
|
createNode(key: K, value?: N['value']): N;
|
|
13
18
|
|
|
14
19
|
createTree(options?: Partial<BinaryTreeOptions<K>>): TREE;
|
package/src/types/common.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export enum BSTVariant {
|
|
2
2
|
MIN = 'MIN',
|
|
3
|
-
MAX = 'MAX'
|
|
3
|
+
MAX = 'MAX'
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
export enum CP {
|
|
@@ -46,15 +46,15 @@ export interface IterableWithLength<T> extends Iterable<T> {
|
|
|
46
46
|
length: number | ((...args: any[]) => number);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export type IterableWithSizeOrLength<T> = IterableWithSize<T> | IterableWithLength<T
|
|
49
|
+
export type IterableWithSizeOrLength<T> = IterableWithSize<T> | IterableWithLength<T>;
|
|
50
50
|
|
|
51
|
-
export type BinaryTreePrintOptions = { isShowUndefined?: boolean
|
|
51
|
+
export type BinaryTreePrintOptions = { isShowUndefined?: boolean; isShowNull?: boolean; isShowRedBlackNIL?: boolean };
|
|
52
52
|
|
|
53
53
|
export type BTNEntry<K, V> = [K | null | undefined, V | undefined];
|
|
54
54
|
|
|
55
55
|
export type BTNKeyOrNode<K, N> = K | null | undefined | N;
|
|
56
56
|
|
|
57
|
-
export type BTNExemplar<K, V, N> = BTNEntry<K, V> | BTNKeyOrNode<K, N
|
|
57
|
+
export type BTNExemplar<K, V, N> = BTNEntry<K, V> | BTNKeyOrNode<K, N>;
|
|
58
58
|
|
|
59
59
|
export type BTNodePureKeyOrNode<K, N> = K | N;
|
|
60
60
|
|