data-structure-typed 2.0.0 → 2.0.2
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/CHANGELOG.md +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +8 -9
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/graph/abstract-graph.js +14 -14
- package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.d.ts +46 -0
- package/dist/cjs/data-structures/hash/hash-map.js +46 -0
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +66 -0
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js +66 -0
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.d.ts +47 -0
- package/dist/cjs/data-structures/queue/queue.js +47 -0
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/cjs/data-structures/stack/stack.d.ts +121 -0
- package/dist/cjs/data-structures/stack/stack.js +121 -0
- package/dist/cjs/data-structures/stack/stack.js.map +1 -1
- package/dist/cjs/types/utils/utils.d.ts +1 -7
- package/dist/cjs/utils/utils.d.ts +3 -49
- package/dist/cjs/utils/utils.js +13 -82
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/binary-tree.js +8 -9
- package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/esm/data-structures/graph/abstract-graph.js +14 -14
- package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/esm/data-structures/hash/hash-map.d.ts +46 -0
- package/dist/esm/data-structures/hash/hash-map.js +46 -0
- package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
- package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +66 -0
- package/dist/esm/data-structures/linked-list/singly-linked-list.js +66 -0
- package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/esm/data-structures/queue/queue.d.ts +47 -0
- package/dist/esm/data-structures/queue/queue.js +47 -0
- package/dist/esm/data-structures/queue/queue.js.map +1 -1
- package/dist/esm/data-structures/stack/stack.d.ts +121 -0
- package/dist/esm/data-structures/stack/stack.js +121 -0
- package/dist/esm/data-structures/stack/stack.js.map +1 -1
- package/dist/esm/types/utils/utils.d.ts +1 -7
- package/dist/esm/utils/utils.d.ts +3 -49
- package/dist/esm/utils/utils.js +10 -68
- package/dist/esm/utils/utils.js.map +1 -1
- package/dist/umd/data-structure-typed.js +32 -80
- package/dist/umd/data-structure-typed.min.js +2 -2
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/binary-tree/binary-tree.ts +9 -10
- package/src/data-structures/graph/abstract-graph.ts +14 -14
- package/src/data-structures/hash/hash-map.ts +46 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +66 -0
- package/src/data-structures/queue/queue.ts +47 -0
- package/src/data-structures/stack/stack.ts +121 -0
- package/src/types/utils/utils.ts +1 -6
- package/src/utils/utils.ts +11 -83
- package/test/unit/data-structures/graph/directed-graph.test.ts +37 -37
- package/test/unit/data-structures/graph/undirected-graph.test.ts +2 -2
- package/test/unit/data-structures/hash/hash-map.test.ts +135 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +72 -1
- package/test/unit/data-structures/queue/queue.test.ts +214 -0
- package/test/unit/data-structures/stack/stack.test.ts +165 -0
- package/test/unit/utils/utils.test.ts +35 -2
|
@@ -162,3 +162,168 @@ describe('Stack iterative methods', () => {
|
|
|
162
162
|
}).toThrow('toElementFn must be a function type');
|
|
163
163
|
});
|
|
164
164
|
});
|
|
165
|
+
|
|
166
|
+
describe('classic uses', () => {
|
|
167
|
+
it('@example Balanced Parentheses or Brackets', () => {
|
|
168
|
+
type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{';
|
|
169
|
+
|
|
170
|
+
const stack = new Stack<string>();
|
|
171
|
+
const input: ValidCharacters[] = '[({})]'.split('') as ValidCharacters[];
|
|
172
|
+
const matches: { [key in ValidCharacters]?: ValidCharacters } = { ')': '(', ']': '[', '}': '{' };
|
|
173
|
+
for (const char of input) {
|
|
174
|
+
if ('([{'.includes(char)) {
|
|
175
|
+
stack.push(char);
|
|
176
|
+
} else if (')]}'.includes(char)) {
|
|
177
|
+
if (stack.pop() !== matches[char]) {
|
|
178
|
+
fail('Parentheses are not balanced');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
expect(stack.isEmpty()).toBe(true);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('@example Expression Evaluation and Conversion', () => {
|
|
186
|
+
const stack = new Stack<number>();
|
|
187
|
+
const expression = [5, 3, '+']; // Equivalent to 5 + 3
|
|
188
|
+
expression.forEach(token => {
|
|
189
|
+
if (typeof token === 'number') {
|
|
190
|
+
stack.push(token);
|
|
191
|
+
} else {
|
|
192
|
+
const b = stack.pop()!;
|
|
193
|
+
const a = stack.pop()!;
|
|
194
|
+
stack.push(token === '+' ? a + b : 0); // Only handling '+' here
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
expect(stack.pop()).toBe(8);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('@example Depth-First Search (DFS)', () => {
|
|
201
|
+
const stack = new Stack<number>();
|
|
202
|
+
const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] };
|
|
203
|
+
const visited: number[] = [];
|
|
204
|
+
stack.push(1);
|
|
205
|
+
while (!stack.isEmpty()) {
|
|
206
|
+
const node = stack.pop()!;
|
|
207
|
+
if (!visited.includes(node)) {
|
|
208
|
+
visited.push(node);
|
|
209
|
+
graph[node].forEach(neighbor => stack.push(neighbor));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
expect(visited).toEqual([1, 3, 5, 2, 4]); // Example DFS order
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('@example Backtracking Algorithms', () => {
|
|
216
|
+
const stack = new Stack<[number, number]>();
|
|
217
|
+
const maze = [
|
|
218
|
+
['S', ' ', 'X'],
|
|
219
|
+
['X', ' ', 'X'],
|
|
220
|
+
[' ', ' ', 'E']
|
|
221
|
+
];
|
|
222
|
+
const start: [number, number] = [0, 0];
|
|
223
|
+
const end = [2, 2];
|
|
224
|
+
const directions = [
|
|
225
|
+
[0, 1], // To the right
|
|
226
|
+
[1, 0], // down
|
|
227
|
+
[0, -1], // left
|
|
228
|
+
[-1, 0] // up
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
const visited = new Set<string>(); // Used to record visited nodes
|
|
232
|
+
stack.push(start);
|
|
233
|
+
const path: number[][] = [];
|
|
234
|
+
|
|
235
|
+
while (!stack.isEmpty()) {
|
|
236
|
+
const [x, y] = stack.pop()!;
|
|
237
|
+
if (visited.has(`${x},${y}`)) continue; // Skip already visited nodes
|
|
238
|
+
visited.add(`${x},${y}`);
|
|
239
|
+
|
|
240
|
+
path.push([x, y]);
|
|
241
|
+
|
|
242
|
+
if (x === end[0] && y === end[1]) {
|
|
243
|
+
break; // Find the end point and exit
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
for (const [dx, dy] of directions) {
|
|
247
|
+
const nx = x + dx;
|
|
248
|
+
const ny = y + dy;
|
|
249
|
+
if (
|
|
250
|
+
maze[nx]?.[ny] === ' ' || // feasible path
|
|
251
|
+
maze[nx]?.[ny] === 'E' // destination
|
|
252
|
+
) {
|
|
253
|
+
stack.push([nx, ny]);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
expect(path).toContainEqual(end);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('@example Function Call Stack', () => {
|
|
262
|
+
const functionStack = new Stack<string>();
|
|
263
|
+
functionStack.push('main');
|
|
264
|
+
functionStack.push('foo');
|
|
265
|
+
functionStack.push('bar');
|
|
266
|
+
expect(functionStack.pop()).toBe('bar');
|
|
267
|
+
expect(functionStack.pop()).toBe('foo');
|
|
268
|
+
expect(functionStack.pop()).toBe('main');
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('@example Simplify File Paths', () => {
|
|
272
|
+
const stack = new Stack<string>();
|
|
273
|
+
const path = '/a/./b/../../c';
|
|
274
|
+
path.split('/').forEach(segment => {
|
|
275
|
+
if (segment === '..') stack.pop();
|
|
276
|
+
else if (segment && segment !== '.') stack.push(segment);
|
|
277
|
+
});
|
|
278
|
+
expect(stack.elements.join('/')).toBe('c');
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('@example Stock Span Problem', () => {
|
|
282
|
+
const stack = new Stack<number>();
|
|
283
|
+
const prices = [100, 80, 60, 70, 60, 75, 85];
|
|
284
|
+
const spans: number[] = [];
|
|
285
|
+
prices.forEach((price, i) => {
|
|
286
|
+
while (!stack.isEmpty() && prices[stack.peek()!] <= price) {
|
|
287
|
+
stack.pop();
|
|
288
|
+
}
|
|
289
|
+
spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!);
|
|
290
|
+
stack.push(i);
|
|
291
|
+
});
|
|
292
|
+
expect(spans).toEqual([1, 1, 1, 2, 1, 4, 6]);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('Browser Navigation', () => {
|
|
296
|
+
const backStack = new Stack<string>();
|
|
297
|
+
const forwardStack = new Stack<string>();
|
|
298
|
+
backStack.push('Page 1');
|
|
299
|
+
backStack.push('Page 2');
|
|
300
|
+
forwardStack.push(backStack.pop()!);
|
|
301
|
+
expect(backStack.size).toBe(1);
|
|
302
|
+
expect(forwardStack.size).toBe(1);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('String Reversal', () => {
|
|
306
|
+
const stack = new Stack<string>();
|
|
307
|
+
const input = 'hello';
|
|
308
|
+
const reversed = [];
|
|
309
|
+
input.split('').forEach(char => stack.push(char));
|
|
310
|
+
while (!stack.isEmpty()) {
|
|
311
|
+
reversed.push(stack.pop());
|
|
312
|
+
}
|
|
313
|
+
expect(reversed.join('')).toBe('olleh');
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('Next Greater Element', () => {
|
|
317
|
+
const stack = new Stack<number>();
|
|
318
|
+
const array = [4, 5, 2, 25];
|
|
319
|
+
const nextGreater = new Array(array.length).fill(-1);
|
|
320
|
+
array.forEach((_, i) => {
|
|
321
|
+
while (!stack.isEmpty() && array[stack.peek()!] < array[i]) {
|
|
322
|
+
const idx = stack.pop()!;
|
|
323
|
+
nextGreater[idx] = array[i];
|
|
324
|
+
}
|
|
325
|
+
stack.push(i);
|
|
326
|
+
});
|
|
327
|
+
expect(nextGreater).toEqual([5, 25, 25, -1]);
|
|
328
|
+
});
|
|
329
|
+
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { isComparable, trampoline } from '../../../src';
|
|
2
|
+
|
|
1
3
|
describe('isNaN', () => {
|
|
2
4
|
it('should isNaN', function () {
|
|
3
5
|
expect(isNaN('string' as unknown as number)).toBe(true);
|
|
4
6
|
});
|
|
5
7
|
});
|
|
6
8
|
|
|
7
|
-
import { isComparable } from '../../../src';
|
|
8
|
-
|
|
9
9
|
describe('isComparable', () => {
|
|
10
10
|
describe('primitive types', () => {
|
|
11
11
|
it('numbers should be comparable', () => {
|
|
@@ -172,3 +172,36 @@ describe('isComparable', () => {
|
|
|
172
172
|
});
|
|
173
173
|
});
|
|
174
174
|
});
|
|
175
|
+
|
|
176
|
+
describe('Factorial Performance Tests', () => {
|
|
177
|
+
const depth = 5000;
|
|
178
|
+
let arr: number[];
|
|
179
|
+
|
|
180
|
+
const recurseTrampoline = (n: number, arr: number[], acc = 1): (() => any) | number => {
|
|
181
|
+
if (n === 0) return acc;
|
|
182
|
+
arr.unshift(1);
|
|
183
|
+
return () => recurseTrampoline(n - 1, arr, acc);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const recurse = (n: number, arr: number[], acc = 1): number => {
|
|
187
|
+
if (n === 0) return acc;
|
|
188
|
+
arr.unshift(1);
|
|
189
|
+
return recurse(n - 1, arr, acc);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
beforeEach(() => {
|
|
193
|
+
arr = new Array(depth).fill(0);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should calculate recursive function using trampoline without stack overflow', () => {
|
|
197
|
+
const result = trampoline(() => recurseTrampoline(depth, arr));
|
|
198
|
+
expect(result).toBe(1);
|
|
199
|
+
expect(arr.length).toBe(depth + depth);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('should calculate recursive directly and possibly stack overflow', () => {
|
|
203
|
+
const result = recurse(depth, arr);
|
|
204
|
+
expect(result).toBe(1);
|
|
205
|
+
expect(arr.length).toBe(depth + depth);
|
|
206
|
+
});
|
|
207
|
+
});
|