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
|
@@ -341,9 +341,9 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
341
341
|
expect(distMap.get(vertex3)).toBe(35);
|
|
342
342
|
expect(distMap.get(vertex4)).toBe(14);
|
|
343
343
|
expect(distMap.get(vertex5)).toBe(70);
|
|
344
|
-
expect(distMap.get(vertex6)).toBe(
|
|
344
|
+
expect(distMap.get(vertex6)).toBe(Number.MAX_SAFE_INTEGER);
|
|
345
345
|
expect(distMap.get(vertex7)).toBe(61);
|
|
346
|
-
expect(distMap.get(vertex8)).toBe(
|
|
346
|
+
expect(distMap.get(vertex8)).toBe(Number.MAX_SAFE_INTEGER);
|
|
347
347
|
expect(distMap.get(vertex9)).toBe(19);
|
|
348
348
|
|
|
349
349
|
expect(preMap).toBeInstanceOf(Map);
|
|
@@ -351,7 +351,7 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
351
351
|
|
|
352
352
|
expect(paths).toBeInstanceOf(Array);
|
|
353
353
|
expect(paths.length).toBe(0);
|
|
354
|
-
expect(min).toBe(
|
|
354
|
+
expect(min).toBe(Number.MAX_SAFE_INTEGER);
|
|
355
355
|
expect(minPath).toBeInstanceOf(Array);
|
|
356
356
|
|
|
357
357
|
const floydResult = myGraph.floydWarshall();
|
|
@@ -360,35 +360,35 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
360
360
|
const { costs, predecessor } = floydResult;
|
|
361
361
|
expect(costs).toBeInstanceOf(Array);
|
|
362
362
|
expect(costs.length).toBe(9);
|
|
363
|
-
expect(costs[0]).toEqual([32, 12, 35, 14, 70,
|
|
364
|
-
expect(costs[1]).toEqual([20, 32, 23, 34, 58,
|
|
365
|
-
expect(costs[2]).toEqual([3, 15, 38, 17, 35,
|
|
366
|
-
expect(costs[3]).toEqual([123, 135, 120, 137, 155,
|
|
367
|
-
expect(costs[4]).toEqual([133, 145, 130, 147, 165,
|
|
363
|
+
expect(costs[0]).toEqual([32, 12, 35, 14, 70, Number.MAX_SAFE_INTEGER, 61, Number.MAX_SAFE_INTEGER, 19]);
|
|
364
|
+
expect(costs[1]).toEqual([20, 32, 23, 34, 58, Number.MAX_SAFE_INTEGER, 81, Number.MAX_SAFE_INTEGER, 39]);
|
|
365
|
+
expect(costs[2]).toEqual([3, 15, 38, 17, 35, Number.MAX_SAFE_INTEGER, 64, Number.MAX_SAFE_INTEGER, 22]);
|
|
366
|
+
expect(costs[3]).toEqual([123, 135, 120, 137, 155, Number.MAX_SAFE_INTEGER, 47, Number.MAX_SAFE_INTEGER, 126]);
|
|
367
|
+
expect(costs[4]).toEqual([133, 145, 130, 147, 165, Number.MAX_SAFE_INTEGER, 57, Number.MAX_SAFE_INTEGER, 136]);
|
|
368
368
|
expect(costs[5]).toEqual([
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
369
|
+
Number.MAX_SAFE_INTEGER,
|
|
370
|
+
Number.MAX_SAFE_INTEGER,
|
|
371
|
+
Number.MAX_SAFE_INTEGER,
|
|
372
|
+
Number.MAX_SAFE_INTEGER,
|
|
373
|
+
Number.MAX_SAFE_INTEGER,
|
|
374
|
+
Number.MAX_SAFE_INTEGER,
|
|
375
|
+
Number.MAX_SAFE_INTEGER,
|
|
376
|
+
Number.MAX_SAFE_INTEGER,
|
|
377
|
+
Number.MAX_SAFE_INTEGER
|
|
378
378
|
]);
|
|
379
|
-
expect(costs[6]).toEqual([76, 88, 73, 90, 108,
|
|
379
|
+
expect(costs[6]).toEqual([76, 88, 73, 90, 108, Number.MAX_SAFE_INTEGER, 137, Number.MAX_SAFE_INTEGER, 79]);
|
|
380
380
|
expect(costs[7]).toEqual([
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
381
|
+
Number.MAX_SAFE_INTEGER,
|
|
382
|
+
Number.MAX_SAFE_INTEGER,
|
|
383
|
+
Number.MAX_SAFE_INTEGER,
|
|
384
|
+
Number.MAX_SAFE_INTEGER,
|
|
385
|
+
Number.MAX_SAFE_INTEGER,
|
|
386
|
+
Number.MAX_SAFE_INTEGER,
|
|
387
|
+
Number.MAX_SAFE_INTEGER,
|
|
388
|
+
Number.MAX_SAFE_INTEGER,
|
|
389
|
+
Number.MAX_SAFE_INTEGER
|
|
390
390
|
]);
|
|
391
|
-
expect(costs[8]).toEqual([173, 185, 170, 187, 205,
|
|
391
|
+
expect(costs[8]).toEqual([173, 185, 170, 187, 205, Number.MAX_SAFE_INTEGER, 97, Number.MAX_SAFE_INTEGER, 176]);
|
|
392
392
|
|
|
393
393
|
expect(predecessor).toBeInstanceOf(Array);
|
|
394
394
|
expect(predecessor.length).toBe(9);
|
|
@@ -458,12 +458,12 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
458
458
|
expect(distMap.size).toBe(9);
|
|
459
459
|
expect(distMap.get(vertex1)).toBe(0);
|
|
460
460
|
expect(distMap.get(vertex2)).toBe(12);
|
|
461
|
-
expect(distMap.get(vertex3)).toBe(
|
|
461
|
+
expect(distMap.get(vertex3)).toBe(Number.MAX_SAFE_INTEGER);
|
|
462
462
|
expect(distMap.get(vertex4)).toBe(14);
|
|
463
|
-
expect(distMap.get(vertex5)).toBe(
|
|
464
|
-
expect(distMap.get(vertex6)).toBe(
|
|
465
|
-
expect(distMap.get(vertex7)).toBe(
|
|
466
|
-
expect(distMap.get(vertex8)).toBe(
|
|
463
|
+
expect(distMap.get(vertex5)).toBe(Number.MAX_SAFE_INTEGER);
|
|
464
|
+
expect(distMap.get(vertex6)).toBe(Number.MAX_SAFE_INTEGER);
|
|
465
|
+
expect(distMap.get(vertex7)).toBe(Number.MAX_SAFE_INTEGER);
|
|
466
|
+
expect(distMap.get(vertex8)).toBe(Number.MAX_SAFE_INTEGER);
|
|
467
467
|
expect(distMap.get(vertex9)).toBe(19);
|
|
468
468
|
|
|
469
469
|
expect(minDist).toBe(12);
|
|
@@ -512,9 +512,9 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
512
512
|
expect(distMap.get(vertex3)).toBe(35);
|
|
513
513
|
expect(distMap.get(vertex4)).toBe(14);
|
|
514
514
|
expect(distMap.get(vertex5)).toBe(70);
|
|
515
|
-
expect(distMap.get(vertex6)).toBe(
|
|
515
|
+
expect(distMap.get(vertex6)).toBe(Number.MAX_SAFE_INTEGER);
|
|
516
516
|
expect(distMap.get(vertex7)).toBe(61);
|
|
517
|
-
expect(distMap.get(vertex8)).toBe(
|
|
517
|
+
expect(distMap.get(vertex8)).toBe(Number.MAX_SAFE_INTEGER);
|
|
518
518
|
expect(distMap.get(vertex9)).toBe(19);
|
|
519
519
|
|
|
520
520
|
expect(minDist).toBe(12);
|
|
@@ -574,9 +574,9 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
574
574
|
expect(distMap.get(vertex3)).toBe(35);
|
|
575
575
|
expect(distMap.get(vertex4)).toBe(14);
|
|
576
576
|
expect(distMap.get(vertex5)).toBe(70);
|
|
577
|
-
expect(distMap.get(vertex6)).toBe(
|
|
577
|
+
expect(distMap.get(vertex6)).toBe(Number.MAX_SAFE_INTEGER);
|
|
578
578
|
expect(distMap.get(vertex7)).toBe(61);
|
|
579
|
-
expect(distMap.get(vertex8)).toBe(
|
|
579
|
+
expect(distMap.get(vertex8)).toBe(Number.MAX_SAFE_INTEGER);
|
|
580
580
|
expect(distMap.get(vertex9)).toBe(19);
|
|
581
581
|
|
|
582
582
|
expect(minDist).toBe(12);
|
|
@@ -264,7 +264,7 @@ describe('cycles, strongly connected components, bridges, articular points in Un
|
|
|
264
264
|
expect(lowMap.size).toBe(8);
|
|
265
265
|
});
|
|
266
266
|
|
|
267
|
-
it('Should return
|
|
267
|
+
it('Should return Number.MAX_SAFE_INTEGER if dest is not found', () => {
|
|
268
268
|
const graph = new UndirectedGraph<string>();
|
|
269
269
|
|
|
270
270
|
for (let i = 0; i < 3; ++i) {
|
|
@@ -274,7 +274,7 @@ it('Should return Infinity if dest is not found', () => {
|
|
|
274
274
|
graph.addEdge(0, 1, 1);
|
|
275
275
|
|
|
276
276
|
const minCost02 = graph.getMinCostBetween(0, 2, true);
|
|
277
|
-
expect(minCost02).toBe(
|
|
277
|
+
expect(minCost02).toBe(Number.MAX_SAFE_INTEGER);
|
|
278
278
|
|
|
279
279
|
const minCost01 = graph.getMinCostBetween(0, 1, true);
|
|
280
280
|
expect(minCost01).toBe(1);
|
|
@@ -842,3 +842,138 @@ describe('LinkedHashMap', () => {
|
|
|
842
842
|
});
|
|
843
843
|
});
|
|
844
844
|
});
|
|
845
|
+
|
|
846
|
+
describe('classic uses', () => {
|
|
847
|
+
it('@example should maintain insertion order', () => {
|
|
848
|
+
const linkedHashMap = new LinkedHashMap<number, string>();
|
|
849
|
+
linkedHashMap.set(1, 'A');
|
|
850
|
+
linkedHashMap.set(2, 'B');
|
|
851
|
+
linkedHashMap.set(3, 'C');
|
|
852
|
+
|
|
853
|
+
const result = Array.from(linkedHashMap);
|
|
854
|
+
expect(result).toEqual([
|
|
855
|
+
[1, 'A'],
|
|
856
|
+
[2, 'B'],
|
|
857
|
+
[3, 'C']
|
|
858
|
+
]);
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
it('should allow reverse iteration', () => {
|
|
862
|
+
const linkedHashMap = new LinkedHashMap<number, string>();
|
|
863
|
+
linkedHashMap.set(1, 'A');
|
|
864
|
+
linkedHashMap.set(2, 'B');
|
|
865
|
+
linkedHashMap.set(3, 'C');
|
|
866
|
+
|
|
867
|
+
const result = Array.from(linkedHashMap.reverseBegin());
|
|
868
|
+
expect(result).toEqual([
|
|
869
|
+
[3, 'C'],
|
|
870
|
+
[2, 'B'],
|
|
871
|
+
[1, 'A']
|
|
872
|
+
]);
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
it('should allow fast deletion at an index', () => {
|
|
876
|
+
const linkedHashMap = new LinkedHashMap<number, string>();
|
|
877
|
+
linkedHashMap.set(1, 'A');
|
|
878
|
+
linkedHashMap.set(2, 'B');
|
|
879
|
+
linkedHashMap.set(3, 'C');
|
|
880
|
+
|
|
881
|
+
linkedHashMap.deleteAt(1);
|
|
882
|
+
|
|
883
|
+
const result = Array.from(linkedHashMap);
|
|
884
|
+
expect(result).toEqual([
|
|
885
|
+
[1, 'A'],
|
|
886
|
+
[3, 'C']
|
|
887
|
+
]);
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
it('should filter entries correctly', () => {
|
|
891
|
+
const linkedHashMap = new LinkedHashMap<number, string>();
|
|
892
|
+
linkedHashMap.set(1, 'A');
|
|
893
|
+
linkedHashMap.set(2, 'B');
|
|
894
|
+
linkedHashMap.set(3, 'C');
|
|
895
|
+
|
|
896
|
+
const filteredMap = linkedHashMap.filter((key, value) => value !== 'B');
|
|
897
|
+
|
|
898
|
+
const result = Array.from(filteredMap);
|
|
899
|
+
expect(result).toEqual([
|
|
900
|
+
[1, 'A'],
|
|
901
|
+
[3, 'C']
|
|
902
|
+
]);
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
it('should map entries to a new LinkedHashMap', () => {
|
|
906
|
+
const linkedHashMap = new LinkedHashMap<number, string>();
|
|
907
|
+
linkedHashMap.set(1, 'A');
|
|
908
|
+
linkedHashMap.set(2, 'B');
|
|
909
|
+
|
|
910
|
+
const mappedMap = linkedHashMap.map((key, value) => [value, key]);
|
|
911
|
+
|
|
912
|
+
const result = Array.from(mappedMap);
|
|
913
|
+
expect(result).toEqual([
|
|
914
|
+
['A', 1],
|
|
915
|
+
['B', 2]
|
|
916
|
+
]);
|
|
917
|
+
});
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
describe('classic uses', () => {
|
|
921
|
+
it('@example fast lookup of values by key', () => {
|
|
922
|
+
const hashMap = new HashMap<number, string>();
|
|
923
|
+
hashMap.set(1, 'A');
|
|
924
|
+
hashMap.set(2, 'B');
|
|
925
|
+
hashMap.set(3, 'C');
|
|
926
|
+
|
|
927
|
+
expect(hashMap.get(1)).toBe('A');
|
|
928
|
+
expect(hashMap.get(2)).toBe('B');
|
|
929
|
+
expect(hashMap.get(3)).toBe('C');
|
|
930
|
+
expect(hashMap.get(99)).toBeUndefined(); // Key not present
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
it('@example remove duplicates when adding multiple entries', () => {
|
|
934
|
+
const hashMap = new HashMap<number, string>();
|
|
935
|
+
hashMap.set(1, 'A');
|
|
936
|
+
hashMap.set(2, 'B');
|
|
937
|
+
hashMap.set(1, 'C'); // Update value for key 1
|
|
938
|
+
|
|
939
|
+
expect(hashMap.size).toBe(2);
|
|
940
|
+
expect(hashMap.get(1)).toBe('C');
|
|
941
|
+
expect(hashMap.get(2)).toBe('B');
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
it('@example count occurrences of keys', () => {
|
|
945
|
+
const data = [1, 2, 1, 3, 2, 1];
|
|
946
|
+
|
|
947
|
+
const countMap = new HashMap<number, number>();
|
|
948
|
+
for (const key of data) {
|
|
949
|
+
countMap.set(key, (countMap.get(key) || 0) + 1);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
expect(countMap.get(1)).toBe(3);
|
|
953
|
+
expect(countMap.get(2)).toBe(2);
|
|
954
|
+
expect(countMap.get(3)).toBe(1);
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
it('should group entries by a key-derived property', () => {
|
|
958
|
+
const entries = [
|
|
959
|
+
{ id: 1, group: 'A' },
|
|
960
|
+
{ id: 2, group: 'B' },
|
|
961
|
+
{ id: 3, group: 'A' },
|
|
962
|
+
{ id: 4, group: 'B' }
|
|
963
|
+
];
|
|
964
|
+
|
|
965
|
+
const groupedMap = new HashMap<string, number[]>();
|
|
966
|
+
|
|
967
|
+
for (const entry of entries) {
|
|
968
|
+
const group = entry.group;
|
|
969
|
+
const id = entry.id;
|
|
970
|
+
if (!groupedMap.has(group)) {
|
|
971
|
+
groupedMap.set(group, []);
|
|
972
|
+
}
|
|
973
|
+
groupedMap.get(group)?.push(id);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
expect(groupedMap.get('A')).toEqual([1, 3]);
|
|
977
|
+
expect(groupedMap.get('B')).toEqual([2, 4]);
|
|
978
|
+
});
|
|
979
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SinglyLinkedList, SinglyLinkedListNode } from '../../../../src';
|
|
1
|
+
import { SinglyLinkedList, SinglyLinkedListNode, Stack } from '../../../../src';
|
|
2
2
|
|
|
3
3
|
describe('SinglyLinkedListNode', () => {
|
|
4
4
|
it('should SinglyLinkedList', () => {
|
|
@@ -649,3 +649,74 @@ describe('iterable methods', () => {
|
|
|
649
649
|
expect(sl.reduce((accumulator, element) => accumulator + element, 0)).toEqual(6);
|
|
650
650
|
});
|
|
651
651
|
});
|
|
652
|
+
|
|
653
|
+
describe('classic uses', () => {
|
|
654
|
+
|
|
655
|
+
it('@example implementation of a basic text editor', () => {
|
|
656
|
+
|
|
657
|
+
class TextEditor {
|
|
658
|
+
private content: SinglyLinkedList<string>;
|
|
659
|
+
private cursorIndex: number;
|
|
660
|
+
private undoStack: Stack<{ operation: string; data?: any }>;
|
|
661
|
+
|
|
662
|
+
constructor() {
|
|
663
|
+
this.content = new SinglyLinkedList<string>();
|
|
664
|
+
this.cursorIndex = 0; // Cursor starts at the beginning
|
|
665
|
+
this.undoStack = new Stack<{ operation: string; data?: any }>(); // Stack to keep track of operations for undo
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
insert(char: string) {
|
|
669
|
+
this.content.addAt(this.cursorIndex, char);
|
|
670
|
+
this.cursorIndex++;
|
|
671
|
+
this.undoStack.push({ operation: 'insert', data: { index: this.cursorIndex - 1 } });
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
delete() {
|
|
675
|
+
if (this.cursorIndex === 0) return; // Nothing to delete
|
|
676
|
+
const deleted = this.content.deleteAt(this.cursorIndex - 1);
|
|
677
|
+
this.cursorIndex--;
|
|
678
|
+
this.undoStack.push({ operation: 'delete', data: { index: this.cursorIndex, char: deleted } });
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
moveCursor(index: number) {
|
|
682
|
+
this.cursorIndex = Math.max(0, Math.min(index, this.content.length));
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
undo() {
|
|
686
|
+
if (this.undoStack.size === 0) return; // No operations to undo
|
|
687
|
+
const lastAction = this.undoStack.pop();
|
|
688
|
+
|
|
689
|
+
if (lastAction!.operation === 'insert') {
|
|
690
|
+
this.content.deleteAt(lastAction!.data.index);
|
|
691
|
+
this.cursorIndex = lastAction!.data.index;
|
|
692
|
+
} else if (lastAction!.operation === 'delete') {
|
|
693
|
+
this.content.addAt(lastAction!.data.index, lastAction!.data.char);
|
|
694
|
+
this.cursorIndex = lastAction!.data.index + 1;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
getText(): string {
|
|
699
|
+
return [...this.content].join('');
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Example Usage
|
|
704
|
+
const editor = new TextEditor();
|
|
705
|
+
editor.insert('H');
|
|
706
|
+
editor.insert('e');
|
|
707
|
+
editor.insert('l');
|
|
708
|
+
editor.insert('l');
|
|
709
|
+
editor.insert('o');
|
|
710
|
+
expect(editor.getText()).toBe('Hello'); // Output: "Hello"
|
|
711
|
+
|
|
712
|
+
editor.delete();
|
|
713
|
+
expect(editor.getText()).toBe('Hell'); // Output: "Hell"
|
|
714
|
+
|
|
715
|
+
editor.undo();
|
|
716
|
+
expect(editor.getText()).toBe('Hello'); // Output: "Hello"
|
|
717
|
+
|
|
718
|
+
editor.moveCursor(1);
|
|
719
|
+
editor.insert('a');
|
|
720
|
+
expect(editor.getText()).toBe('Haello'); // Output: "Haello"
|
|
721
|
+
});
|
|
722
|
+
});
|
|
@@ -454,3 +454,217 @@ describe('LinkedListQueue', () => {
|
|
|
454
454
|
expect(cloned.length).toBe(2);
|
|
455
455
|
});
|
|
456
456
|
});
|
|
457
|
+
|
|
458
|
+
describe('Queue', () => {
|
|
459
|
+
// Test queue initialization
|
|
460
|
+
it('should initialize correctly with no elements', () => {
|
|
461
|
+
const queue = new Queue();
|
|
462
|
+
expect(queue.isEmpty()).toBe(true);
|
|
463
|
+
expect(queue.length).toBe(0);
|
|
464
|
+
expect(queue.first).toBeUndefined();
|
|
465
|
+
expect(queue.last).toBeUndefined();
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
it('should initialize correctly with given elements', () => {
|
|
469
|
+
const queue = new Queue([1, 2, 3]);
|
|
470
|
+
expect(queue.length).toBe(3);
|
|
471
|
+
expect(queue.first).toBe(1);
|
|
472
|
+
expect(queue.last).toBe(3);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// Test push and pushMany
|
|
476
|
+
it('should add elements to the queue', () => {
|
|
477
|
+
const queue = new Queue<number>();
|
|
478
|
+
queue.push(1);
|
|
479
|
+
queue.push(2);
|
|
480
|
+
expect(queue.length).toBe(2);
|
|
481
|
+
expect(queue.first).toBe(1);
|
|
482
|
+
expect(queue.last).toBe(2);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
it('should add multiple elements using pushMany', () => {
|
|
486
|
+
const queue = new Queue<number>();
|
|
487
|
+
queue.pushMany([1, 2, 3]);
|
|
488
|
+
expect(queue.length).toBe(3);
|
|
489
|
+
expect(queue.elements).toEqual([1, 2, 3]);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// Test shift
|
|
493
|
+
it('should remove the first element from the queue', () => {
|
|
494
|
+
const queue = new Queue([1, 2, 3]);
|
|
495
|
+
const shifted = queue.shift();
|
|
496
|
+
expect(shifted).toBe(1);
|
|
497
|
+
expect(queue.length).toBe(2);
|
|
498
|
+
expect(queue.first).toBe(2);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// Test delete and deleteAt
|
|
502
|
+
it('should delete an element from the queue', () => {
|
|
503
|
+
const queue = new Queue([1, 2, 3]);
|
|
504
|
+
const result = queue.delete(2);
|
|
505
|
+
expect(result).toBe(true);
|
|
506
|
+
expect(queue.elements).toEqual([1, 3]);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
it('should delete an element at a specific index', () => {
|
|
510
|
+
const queue = new Queue([1, 2, 3]);
|
|
511
|
+
const deleted = queue.deleteAt(1);
|
|
512
|
+
expect(deleted).toBe(2);
|
|
513
|
+
expect(queue.elements).toEqual([1, 3]);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
// Test at
|
|
517
|
+
it('should retrieve an element by index', () => {
|
|
518
|
+
const queue = new Queue([1, 2, 3]);
|
|
519
|
+
expect(queue.at(0)).toBe(1);
|
|
520
|
+
expect(queue.at(2)).toBe(3);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// Test reverse
|
|
524
|
+
it('should reverse the queue', () => {
|
|
525
|
+
const queue = new Queue([1, 2, 3]);
|
|
526
|
+
queue.reverse();
|
|
527
|
+
expect(queue.elements).toEqual([3, 2, 1]);
|
|
528
|
+
expect(queue.first).toBe(3);
|
|
529
|
+
expect(queue.last).toBe(1);
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// Test addAt
|
|
533
|
+
it('should add an element at a specific index', () => {
|
|
534
|
+
const queue = new Queue([1, 3]);
|
|
535
|
+
const result = queue.addAt(1, 2);
|
|
536
|
+
expect(result).toBe(true);
|
|
537
|
+
expect(queue.elements).toEqual([1, 2, 3]);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// Test setAt
|
|
541
|
+
it('should set an element at a specific index', () => {
|
|
542
|
+
const queue = new Queue([1, 2, 3]);
|
|
543
|
+
const result = queue.setAt(1, 10);
|
|
544
|
+
expect(result).toBe(true);
|
|
545
|
+
expect(queue.elements).toEqual([1, 10, 3]);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// Test clear
|
|
549
|
+
it('should clear the queue', () => {
|
|
550
|
+
const queue = new Queue([1, 2, 3]);
|
|
551
|
+
queue.clear();
|
|
552
|
+
expect(queue.isEmpty()).toBe(true);
|
|
553
|
+
expect(queue.length).toBe(0);
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
// Test compact
|
|
557
|
+
it('should compact the queue', () => {
|
|
558
|
+
const queue = new Queue([1, 2, 3]);
|
|
559
|
+
queue.shift();
|
|
560
|
+
queue.shift();
|
|
561
|
+
queue.compact();
|
|
562
|
+
expect(queue.elements).toEqual([3]);
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// Test splice
|
|
566
|
+
it('should splice elements from the queue', () => {
|
|
567
|
+
const queue = new Queue([1, 2, 3, 4]);
|
|
568
|
+
const removed = queue.splice(1, 2);
|
|
569
|
+
expect(removed.elements).toEqual([2, 3]);
|
|
570
|
+
expect(queue.elements).toEqual([1, 4]);
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// Test clone
|
|
574
|
+
it('should create a clone of the queue', () => {
|
|
575
|
+
const queue = new Queue([1, 2, 3]);
|
|
576
|
+
const clone = queue.clone();
|
|
577
|
+
expect(clone.elements).toEqual(queue.elements);
|
|
578
|
+
clone.push(4);
|
|
579
|
+
expect(queue.elements).not.toContain(4);
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
// Test filter
|
|
583
|
+
it('should filter elements based on a predicate', () => {
|
|
584
|
+
const queue = new Queue([1, 2, 3, 4]);
|
|
585
|
+
const filtered = queue.filter(el => el % 2 === 0);
|
|
586
|
+
expect(filtered.elements).toEqual([2, 4]);
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
// Test map
|
|
590
|
+
it('should map elements to a new queue', () => {
|
|
591
|
+
const queue = new Queue([1, 2, 3]);
|
|
592
|
+
const mapped = queue.map(el => el * 2);
|
|
593
|
+
expect(mapped.elements).toEqual([2, 4, 6]);
|
|
594
|
+
});
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
describe('classic uses', () => {
|
|
598
|
+
it('@example Sliding Window using Queue', () => {
|
|
599
|
+
const nums = [2, 3, 4, 1, 5];
|
|
600
|
+
const k = 2;
|
|
601
|
+
const queue = new Queue<number>();
|
|
602
|
+
|
|
603
|
+
let maxSum = 0;
|
|
604
|
+
let currentSum = 0;
|
|
605
|
+
|
|
606
|
+
nums.forEach((num) => {
|
|
607
|
+
queue.push(num);
|
|
608
|
+
currentSum += num;
|
|
609
|
+
|
|
610
|
+
if (queue.length > k) {
|
|
611
|
+
currentSum -= queue.shift()!;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (queue.length === k) {
|
|
615
|
+
maxSum = Math.max(maxSum, currentSum);
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
expect(maxSum).toBe(7); // Maximum sum is from subarray [3, 4].
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
it('@example Breadth-First Search (BFS) using Queue', () => {
|
|
623
|
+
const graph: { [key in number]: number[] } = {
|
|
624
|
+
1: [2, 3],
|
|
625
|
+
2: [4, 5],
|
|
626
|
+
3: [],
|
|
627
|
+
4: [],
|
|
628
|
+
5: []
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
const queue = new Queue<number>();
|
|
632
|
+
const visited: number[] = [];
|
|
633
|
+
|
|
634
|
+
queue.push(1);
|
|
635
|
+
|
|
636
|
+
while (!queue.isEmpty()) {
|
|
637
|
+
const node = queue.shift()!;
|
|
638
|
+
if (!visited.includes(node)) {
|
|
639
|
+
visited.push(node);
|
|
640
|
+
graph[node].forEach(neighbor => queue.push(neighbor));
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
expect(visited).toEqual([1, 2, 3, 4, 5]); // Expected BFS traversal order.
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it('Task Scheduling using Queue', () => {
|
|
648
|
+
const tasks = ['A', 'A', 'A', 'B', 'B', 'B'];
|
|
649
|
+
const cooldown = 2;
|
|
650
|
+
|
|
651
|
+
const taskQueue = new Queue<string>();
|
|
652
|
+
const cooldownQueue = new Queue<string>();
|
|
653
|
+
|
|
654
|
+
for (const task of tasks) {
|
|
655
|
+
while (!cooldownQueue.isEmpty() && cooldownQueue.first === task) {
|
|
656
|
+
cooldownQueue.shift();
|
|
657
|
+
taskQueue.push('idle');
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
taskQueue.push(task);
|
|
661
|
+
cooldownQueue.push(task);
|
|
662
|
+
if (cooldownQueue.length > cooldown) {
|
|
663
|
+
cooldownQueue.shift();
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const scheduled = taskQueue.elements;
|
|
668
|
+
expect(scheduled).toEqual(['A', 'idle', 'A', 'idle', 'A', 'B', 'B', 'idle', 'idle', 'B']);
|
|
669
|
+
});
|
|
670
|
+
});
|