data-structure-typed 2.2.2 → 2.2.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/CHANGELOG.md +3 -1
- package/README.md +355 -1672
- package/README_CN.md +509 -0
- package/SECURITY.md +962 -11
- package/SECURITY.zh-CN.md +966 -0
- package/SPECIFICATION.md +689 -30
- package/SPECIFICATION.zh-CN.md +715 -0
- package/SPONSOR.zh-CN.md +62 -0
- package/SPONSOR_POLISHED.md +62 -0
- package/benchmark/report.html +1 -1
- package/benchmark/report.json +215 -172
- package/dist/cjs/index.cjs +245 -72
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +246 -72
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +245 -72
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +246 -72
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +5 -5
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +98 -5
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
- package/dist/types/data-structures/binary-tree/bst.d.ts +202 -39
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +86 -37
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +4 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +7 -7
- package/dist/types/data-structures/graph/directed-graph.d.ts +126 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +160 -1
- package/dist/types/data-structures/hash/hash-map.d.ts +110 -27
- package/dist/types/data-structures/heap/heap.d.ts +107 -58
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +72 -404
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -5
- package/dist/types/data-structures/queue/deque.d.ts +95 -67
- package/dist/types/data-structures/queue/queue.d.ts +90 -34
- package/dist/types/data-structures/stack/stack.d.ts +58 -40
- package/dist/types/data-structures/trie/trie.d.ts +109 -47
- package/dist/types/interfaces/binary-tree.d.ts +1 -0
- package/dist/types/types/data-structures/binary-tree/bst.d.ts +5 -5
- package/dist/umd/data-structure-typed.js +246 -72
- package/dist/umd/data-structure-typed.js.map +1 -1
- package/dist/umd/data-structure-typed.min.js +3 -3
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +3 -2
- package/src/data-structures/binary-tree/avl-tree-counter.ts +1 -2
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +7 -8
- package/src/data-structures/binary-tree/avl-tree.ts +100 -7
- package/src/data-structures/binary-tree/binary-tree.ts +117 -7
- package/src/data-structures/binary-tree/bst.ts +431 -93
- package/src/data-structures/binary-tree/red-black-tree.ts +85 -37
- package/src/data-structures/binary-tree/tree-counter.ts +5 -7
- package/src/data-structures/binary-tree/tree-multi-map.ts +9 -10
- package/src/data-structures/graph/directed-graph.ts +126 -1
- package/src/data-structures/graph/undirected-graph.ts +160 -1
- package/src/data-structures/hash/hash-map.ts +110 -27
- package/src/data-structures/heap/heap.ts +107 -58
- package/src/data-structures/linked-list/doubly-linked-list.ts +72 -404
- package/src/data-structures/linked-list/singly-linked-list.ts +121 -5
- package/src/data-structures/queue/deque.ts +95 -67
- package/src/data-structures/queue/queue.ts +90 -34
- package/src/data-structures/stack/stack.ts +58 -40
- package/src/data-structures/trie/trie.ts +109 -47
- package/src/interfaces/binary-tree.ts +2 -0
- package/src/types/data-structures/binary-tree/bst.ts +5 -5
- package/test/performance/benchmark-runner.ts +14 -11
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +8 -8
- package/test/performance/data-structures/binary-tree/binary-tree-overall.test.ts +8 -8
- package/test/performance/data-structures/binary-tree/binary-tree.test.ts +6 -6
- package/test/performance/data-structures/binary-tree/bst.test.ts +5 -5
- package/test/performance/data-structures/binary-tree/red-black-tree.test.ts +10 -10
- package/test/performance/reportor.ts +2 -1
- package/test/performance/single-suite-runner.ts +7 -4
- package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +117 -0
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +166 -0
- package/test/unit/data-structures/binary-tree/bst.test.ts +771 -16
- package/test/unit/data-structures/binary-tree/overall.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +90 -38
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +2 -2
- package/test/unit/data-structures/graph/directed-graph.test.ts +133 -0
- package/test/unit/data-structures/graph/undirected-graph.test.ts +167 -0
- package/test/unit/data-structures/hash/hash-map.test.ts +149 -3
- package/test/unit/data-structures/heap/heap.test.ts +182 -47
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +118 -14
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +121 -0
- package/test/unit/data-structures/queue/deque.test.ts +98 -67
- package/test/unit/data-structures/queue/queue.test.ts +85 -51
- package/test/unit/data-structures/stack/stack.test.ts +142 -33
- package/test/unit/data-structures/trie/trie.test.ts +135 -39
- package/tsup.leetcode.config.js +99 -0
- package/typedoc.json +2 -1
- package/POSTS_zh-CN.md +0 -54
- package/README_zh-CN.md +0 -1208
- package/SPECIFICATION_zh-CN.md +0 -81
|
@@ -813,93 +813,124 @@ describe('Deque', () => {
|
|
|
813
813
|
});
|
|
814
814
|
|
|
815
815
|
describe('classic uses', () => {
|
|
816
|
-
it('@example
|
|
817
|
-
|
|
818
|
-
|
|
816
|
+
it('@example basic Deque creation and push/pop operations', () => {
|
|
817
|
+
// Create a simple Deque with initial values
|
|
818
|
+
const deque = new Deque([1, 2, 3, 4, 5]);
|
|
819
819
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
this.deque = new Deque<string>(prizes);
|
|
823
|
-
}
|
|
820
|
+
// Verify the deque maintains insertion order
|
|
821
|
+
expect([...deque]).toEqual([1, 2, 3, 4, 5]);
|
|
824
822
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
const n = this.deque.length;
|
|
828
|
-
if (n === 0) return;
|
|
823
|
+
// Check length
|
|
824
|
+
expect(deque.length).toBe(5);
|
|
829
825
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
}
|
|
834
|
-
}
|
|
826
|
+
// Push to the end
|
|
827
|
+
deque.push(6);
|
|
828
|
+
expect(deque.length).toBe(6);
|
|
835
829
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
830
|
+
// Pop from the end
|
|
831
|
+
const last = deque.pop();
|
|
832
|
+
expect(last).toBe(6);
|
|
833
|
+
});
|
|
840
834
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
this.deque.push(first!); // Add it to the back
|
|
844
|
-
}
|
|
845
|
-
}
|
|
835
|
+
it('@example Deque shift and unshift operations', () => {
|
|
836
|
+
const deque = new Deque<number>([20, 30, 40]);
|
|
846
837
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
838
|
+
// Unshift adds to the front
|
|
839
|
+
deque.unshift(10);
|
|
840
|
+
expect([...deque]).toEqual([10, 20, 30, 40]);
|
|
841
|
+
|
|
842
|
+
// Shift removes from the front (O(1) complexity!)
|
|
843
|
+
const first = deque.shift();
|
|
844
|
+
expect(first).toBe(10);
|
|
845
|
+
|
|
846
|
+
// Verify remaining elements
|
|
847
|
+
expect([...deque]).toEqual([20, 30, 40]);
|
|
848
|
+
expect(deque.length).toBe(3);
|
|
849
|
+
});
|
|
852
850
|
|
|
853
|
-
|
|
854
|
-
const
|
|
855
|
-
const roulette = new PrizeRoulette(prizes);
|
|
851
|
+
it('@example Deque peek at both ends', () => {
|
|
852
|
+
const deque = new Deque<number>([10, 20, 30, 40, 50]);
|
|
856
853
|
|
|
857
|
-
//
|
|
858
|
-
|
|
854
|
+
// Get first element without removing
|
|
855
|
+
const first = deque.at(0);
|
|
856
|
+
expect(first).toBe(10);
|
|
859
857
|
|
|
860
|
-
//
|
|
861
|
-
|
|
862
|
-
expect(
|
|
858
|
+
// Get last element without removing
|
|
859
|
+
const last = deque.at(deque.length - 1);
|
|
860
|
+
expect(last).toBe(50);
|
|
863
861
|
|
|
864
|
-
//
|
|
865
|
-
|
|
866
|
-
expect(roulette.display()).toBe('Headphones'); // Headphones
|
|
862
|
+
// Length unchanged
|
|
863
|
+
expect(deque.length).toBe(5);
|
|
867
864
|
});
|
|
868
865
|
|
|
869
|
-
it('@example
|
|
870
|
-
|
|
871
|
-
function maxSlidingWindow(nums: number[], k: number): number[] {
|
|
872
|
-
const n = nums.length;
|
|
873
|
-
if (n * k === 0) return [];
|
|
866
|
+
it('@example Deque for...of iteration and reverse', () => {
|
|
867
|
+
const deque = new Deque<string>(['A', 'B', 'C', 'D']);
|
|
874
868
|
|
|
875
|
-
|
|
876
|
-
|
|
869
|
+
// Iterate forward
|
|
870
|
+
const forward: string[] = [];
|
|
871
|
+
for (const item of deque) {
|
|
872
|
+
forward.push(item);
|
|
873
|
+
}
|
|
874
|
+
expect(forward).toEqual(['A', 'B', 'C', 'D']);
|
|
877
875
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
876
|
+
// Reverse the deque
|
|
877
|
+
deque.reverse();
|
|
878
|
+
const backward: string[] = [];
|
|
879
|
+
for (const item of deque) {
|
|
880
|
+
backward.push(item);
|
|
881
|
+
}
|
|
882
|
+
expect(backward).toEqual(['D', 'C', 'B', 'A']);
|
|
883
|
+
});
|
|
883
884
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
885
|
+
it('@example Deque as sliding window for stream processing', () => {
|
|
886
|
+
interface DataPoint {
|
|
887
|
+
timestamp: number;
|
|
888
|
+
value: number;
|
|
889
|
+
sensor: string;
|
|
890
|
+
}
|
|
888
891
|
|
|
889
|
-
|
|
890
|
-
|
|
892
|
+
// Create a deque-based sliding window for real-time data aggregation
|
|
893
|
+
const windowSize = 3;
|
|
894
|
+
const dataWindow = new Deque<DataPoint>();
|
|
891
895
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
+
// Simulate incoming sensor data stream
|
|
897
|
+
const incomingData: DataPoint[] = [
|
|
898
|
+
{ timestamp: 1000, value: 25.5, sensor: 'temp-01' },
|
|
899
|
+
{ timestamp: 1100, value: 26.2, sensor: 'temp-01' },
|
|
900
|
+
{ timestamp: 1200, value: 25.8, sensor: 'temp-01' },
|
|
901
|
+
{ timestamp: 1300, value: 27.1, sensor: 'temp-01' },
|
|
902
|
+
{ timestamp: 1400, value: 26.9, sensor: 'temp-01' }
|
|
903
|
+
];
|
|
904
|
+
|
|
905
|
+
const windowResults: Array<{ avgValue: number; windowSize: number }> = [];
|
|
906
|
+
|
|
907
|
+
for (const dataPoint of incomingData) {
|
|
908
|
+
// Add new data to the end
|
|
909
|
+
dataWindow.push(dataPoint);
|
|
910
|
+
|
|
911
|
+
// Remove oldest data when window exceeds size (O(1) from front)
|
|
912
|
+
if (dataWindow.length > windowSize) {
|
|
913
|
+
dataWindow.shift();
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// Calculate average of current window
|
|
917
|
+
let sum = 0;
|
|
918
|
+
for (const point of dataWindow) {
|
|
919
|
+
sum += point.value;
|
|
896
920
|
}
|
|
921
|
+
const avg = sum / dataWindow.length;
|
|
897
922
|
|
|
898
|
-
|
|
923
|
+
windowResults.push({
|
|
924
|
+
avgValue: Math.round(avg * 10) / 10,
|
|
925
|
+
windowSize: dataWindow.length
|
|
926
|
+
});
|
|
899
927
|
}
|
|
900
928
|
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
expect(
|
|
929
|
+
// Verify sliding window behavior
|
|
930
|
+
expect(windowResults.length).toBe(5);
|
|
931
|
+
expect(windowResults[0].windowSize).toBe(1); // First window has 1 element
|
|
932
|
+
expect(windowResults[2].windowSize).toBe(3); // Windows are at max size from 3rd onwards
|
|
933
|
+
expect(windowResults[4].windowSize).toBe(3); // Last window still has 3 elements
|
|
934
|
+
expect(dataWindow.length).toBe(3); // Final window contains last 3 elements
|
|
904
935
|
});
|
|
905
936
|
});
|
|
@@ -594,76 +594,110 @@ describe('Queue', () => {
|
|
|
594
594
|
});
|
|
595
595
|
|
|
596
596
|
describe('classic uses', () => {
|
|
597
|
-
it('@example
|
|
598
|
-
|
|
599
|
-
const
|
|
600
|
-
const queue = new Queue<number>();
|
|
597
|
+
it('@example basic Queue creation and push operation', () => {
|
|
598
|
+
// Create a simple Queue with initial values
|
|
599
|
+
const queue = new Queue([1, 2, 3, 4, 5]);
|
|
601
600
|
|
|
602
|
-
|
|
603
|
-
|
|
601
|
+
// Verify the queue maintains insertion order
|
|
602
|
+
expect([...queue]).toEqual([1, 2, 3, 4, 5]);
|
|
604
603
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
604
|
+
// Check length
|
|
605
|
+
expect(queue.length).toBe(5);
|
|
606
|
+
});
|
|
608
607
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
608
|
+
it('@example Queue shift and peek operations', () => {
|
|
609
|
+
const queue = new Queue<number>([10, 20, 30, 40]);
|
|
612
610
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
611
|
+
// Peek at the front element without removing it
|
|
612
|
+
expect(queue.first).toBe(10);
|
|
613
|
+
|
|
614
|
+
// Remove and get the first element (FIFO)
|
|
615
|
+
const first = queue.shift();
|
|
616
|
+
expect(first).toBe(10);
|
|
617
617
|
|
|
618
|
-
|
|
618
|
+
// Verify remaining elements and length decreased
|
|
619
|
+
expect([...queue]).toEqual([20, 30, 40]);
|
|
620
|
+
expect(queue.length).toBe(3);
|
|
619
621
|
});
|
|
620
622
|
|
|
621
|
-
it('@example
|
|
622
|
-
const
|
|
623
|
-
1: [2, 3],
|
|
624
|
-
2: [4, 5],
|
|
625
|
-
3: [],
|
|
626
|
-
4: [],
|
|
627
|
-
5: []
|
|
628
|
-
};
|
|
623
|
+
it('@example Queue for...of iteration and isEmpty check', () => {
|
|
624
|
+
const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
629
625
|
|
|
630
|
-
const
|
|
631
|
-
const
|
|
626
|
+
const elements: string[] = [];
|
|
627
|
+
for (const item of queue) {
|
|
628
|
+
elements.push(item);
|
|
629
|
+
}
|
|
632
630
|
|
|
633
|
-
|
|
631
|
+
// Verify all elements are iterated in order
|
|
632
|
+
expect(elements).toEqual(['A', 'B', 'C', 'D']);
|
|
634
633
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
visited.push(node);
|
|
639
|
-
graph[node].forEach(neighbor => queue.push(neighbor));
|
|
640
|
-
}
|
|
634
|
+
// Process all elements
|
|
635
|
+
while (queue.length > 0) {
|
|
636
|
+
queue.shift();
|
|
641
637
|
}
|
|
642
638
|
|
|
643
|
-
expect(
|
|
639
|
+
expect(queue.length).toBe(0);
|
|
644
640
|
});
|
|
645
641
|
|
|
646
|
-
it('
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
642
|
+
it('@example Queue as message broker for event processing', () => {
|
|
643
|
+
interface Message {
|
|
644
|
+
id: string;
|
|
645
|
+
type: 'email' | 'sms' | 'push';
|
|
646
|
+
recipient: string;
|
|
647
|
+
content: string;
|
|
648
|
+
timestamp: Date;
|
|
649
|
+
}
|
|
652
650
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
651
|
+
// Create a message queue for real-time event processing
|
|
652
|
+
const messageQueue = new Queue<Message>([
|
|
653
|
+
{
|
|
654
|
+
id: 'msg-001',
|
|
655
|
+
type: 'email',
|
|
656
|
+
recipient: 'user@example.com',
|
|
657
|
+
content: 'Welcome!',
|
|
658
|
+
timestamp: new Date()
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
id: 'msg-002',
|
|
662
|
+
type: 'sms',
|
|
663
|
+
recipient: '+1234567890',
|
|
664
|
+
content: 'OTP: 123456',
|
|
665
|
+
timestamp: new Date()
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
id: 'msg-003',
|
|
669
|
+
type: 'push',
|
|
670
|
+
recipient: 'device-token-xyz',
|
|
671
|
+
content: 'New notification',
|
|
672
|
+
timestamp: new Date()
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
id: 'msg-004',
|
|
676
|
+
type: 'email',
|
|
677
|
+
recipient: 'admin@example.com',
|
|
678
|
+
content: 'Daily report',
|
|
679
|
+
timestamp: new Date()
|
|
657
680
|
}
|
|
681
|
+
]);
|
|
658
682
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
683
|
+
// Process messages in FIFO order (first message first)
|
|
684
|
+
const processedMessages: string[] = [];
|
|
685
|
+
while (messageQueue.length > 0) {
|
|
686
|
+
const message = messageQueue.shift();
|
|
687
|
+
if (message) {
|
|
688
|
+
processedMessages.push(`${message.type}:${message.recipient}`);
|
|
663
689
|
}
|
|
664
690
|
}
|
|
665
691
|
|
|
666
|
-
|
|
667
|
-
expect(
|
|
692
|
+
// Verify messages were processed in order
|
|
693
|
+
expect(processedMessages).toEqual([
|
|
694
|
+
'email:user@example.com',
|
|
695
|
+
'sms:+1234567890',
|
|
696
|
+
'push:device-token-xyz',
|
|
697
|
+
'email:admin@example.com'
|
|
698
|
+
]);
|
|
699
|
+
|
|
700
|
+
// Queue should be empty after processing all messages
|
|
701
|
+
expect(messageQueue.length).toBe(0);
|
|
668
702
|
});
|
|
669
703
|
});
|
|
@@ -164,6 +164,50 @@ describe('Stack iterative methods', () => {
|
|
|
164
164
|
});
|
|
165
165
|
|
|
166
166
|
describe('classic uses', () => {
|
|
167
|
+
it('@example basic Stack creation and push operation', () => {
|
|
168
|
+
// Create a simple Stack with initial values
|
|
169
|
+
const stack = new Stack([1, 2, 3, 4, 5]);
|
|
170
|
+
|
|
171
|
+
// Verify the stack maintains insertion order (LIFO will be shown in pop)
|
|
172
|
+
expect([...stack]).toEqual([1, 2, 3, 4, 5]);
|
|
173
|
+
|
|
174
|
+
// Check length
|
|
175
|
+
expect(stack.size).toBe(5);
|
|
176
|
+
|
|
177
|
+
// Push a new element to the top
|
|
178
|
+
stack.push(6);
|
|
179
|
+
expect(stack.size).toBe(6);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('@example Stack pop operation (LIFO - Last In First Out)', () => {
|
|
183
|
+
const stack = new Stack<number>([10, 20, 30, 40, 50]);
|
|
184
|
+
|
|
185
|
+
// Peek at the top element without removing
|
|
186
|
+
const top = stack.peek();
|
|
187
|
+
expect(top).toBe(50);
|
|
188
|
+
|
|
189
|
+
// Pop removes from the top (LIFO order)
|
|
190
|
+
const popped = stack.pop();
|
|
191
|
+
expect(popped).toBe(50);
|
|
192
|
+
|
|
193
|
+
// Next pop gets the previous element
|
|
194
|
+
const next = stack.pop();
|
|
195
|
+
expect(next).toBe(40);
|
|
196
|
+
|
|
197
|
+
// Verify length decreased
|
|
198
|
+
expect(stack.size).toBe(3);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('@example Function Call Stack', () => {
|
|
202
|
+
const functionStack = new Stack<string>();
|
|
203
|
+
functionStack.push('main');
|
|
204
|
+
functionStack.push('foo');
|
|
205
|
+
functionStack.push('bar');
|
|
206
|
+
expect(functionStack.pop()).toBe('bar');
|
|
207
|
+
expect(functionStack.pop()).toBe('foo');
|
|
208
|
+
expect(functionStack.pop()).toBe('main');
|
|
209
|
+
});
|
|
210
|
+
|
|
167
211
|
it('@example Balanced Parentheses or Brackets', () => {
|
|
168
212
|
type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{';
|
|
169
213
|
|
|
@@ -197,21 +241,6 @@ describe('classic uses', () => {
|
|
|
197
241
|
expect(stack.pop()).toBe(8);
|
|
198
242
|
});
|
|
199
243
|
|
|
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
244
|
it('@example Backtracking Algorithms', () => {
|
|
216
245
|
const stack = new Stack<[number, number]>();
|
|
217
246
|
const maze = [
|
|
@@ -258,14 +287,18 @@ describe('classic uses', () => {
|
|
|
258
287
|
expect(path).toContainEqual(end);
|
|
259
288
|
});
|
|
260
289
|
|
|
261
|
-
it('@example
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
290
|
+
it('@example Stock Span Problem', () => {
|
|
291
|
+
const stack = new Stack<number>();
|
|
292
|
+
const prices = [100, 80, 60, 70, 60, 75, 85];
|
|
293
|
+
const spans: number[] = [];
|
|
294
|
+
prices.forEach((price, i) => {
|
|
295
|
+
while (!stack.isEmpty() && prices[stack.peek()!] <= price) {
|
|
296
|
+
stack.pop();
|
|
297
|
+
}
|
|
298
|
+
spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!);
|
|
299
|
+
stack.push(i);
|
|
300
|
+
});
|
|
301
|
+
expect(spans).toEqual([1, 1, 1, 2, 1, 4, 6]);
|
|
269
302
|
});
|
|
270
303
|
|
|
271
304
|
it('@example Simplify File Paths', () => {
|
|
@@ -278,18 +311,94 @@ describe('classic uses', () => {
|
|
|
278
311
|
expect(stack.elements.join('/')).toBe('c');
|
|
279
312
|
});
|
|
280
313
|
|
|
281
|
-
it('
|
|
314
|
+
it('Stack for function call stack simulation', () => {
|
|
315
|
+
interface CallFrame {
|
|
316
|
+
functionName: string;
|
|
317
|
+
lineNumber: number;
|
|
318
|
+
variables: Record<string, unknown>;
|
|
319
|
+
timestamp: number;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Simulate a call stack for debugging/tracing
|
|
323
|
+
const callStack = new Stack<CallFrame>();
|
|
324
|
+
|
|
325
|
+
// Simulate function calls pushing frames onto stack
|
|
326
|
+
callStack.push({
|
|
327
|
+
functionName: 'main',
|
|
328
|
+
lineNumber: 1,
|
|
329
|
+
variables: { x: 10, y: 20 },
|
|
330
|
+
timestamp: 1000
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
callStack.push({
|
|
334
|
+
functionName: 'calculateSum',
|
|
335
|
+
lineNumber: 5,
|
|
336
|
+
variables: { a: 10, b: 20 },
|
|
337
|
+
timestamp: 1100
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
callStack.push({
|
|
341
|
+
functionName: 'helper',
|
|
342
|
+
lineNumber: 12,
|
|
343
|
+
variables: { result: 30 },
|
|
344
|
+
timestamp: 1200
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Verify current call frame
|
|
348
|
+
expect(callStack.size).toBe(3);
|
|
349
|
+
const currentFrame = callStack.peek();
|
|
350
|
+
expect(currentFrame?.functionName).toBe('helper');
|
|
351
|
+
expect(currentFrame?.lineNumber).toBe(12);
|
|
352
|
+
|
|
353
|
+
// Simulate function returns popping from stack (LIFO)
|
|
354
|
+
const returnedFrame = callStack.pop();
|
|
355
|
+
expect(returnedFrame?.functionName).toBe('helper');
|
|
356
|
+
expect(callStack.size).toBe(2);
|
|
357
|
+
|
|
358
|
+
// Next return
|
|
359
|
+
const nextReturn = callStack.pop();
|
|
360
|
+
expect(nextReturn?.functionName).toBe('calculateSum');
|
|
361
|
+
|
|
362
|
+
// Back to main
|
|
363
|
+
const mainFrame = callStack.pop();
|
|
364
|
+
expect(mainFrame?.functionName).toBe('main');
|
|
365
|
+
|
|
366
|
+
// Stack empty after all returns
|
|
367
|
+
expect(callStack.size).toBe(0);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('Stack for...of iteration and isEmpty', () => {
|
|
371
|
+
const stack = new Stack<string>(['A', 'B', 'C', 'D']);
|
|
372
|
+
|
|
373
|
+
// Iterate through stack
|
|
374
|
+
const elements: string[] = [];
|
|
375
|
+
for (const item of stack) {
|
|
376
|
+
elements.push(item);
|
|
377
|
+
}
|
|
378
|
+
expect(elements).toEqual(['A', 'B', 'C', 'D']);
|
|
379
|
+
|
|
380
|
+
// Clear the stack
|
|
381
|
+
while (stack.size > 0) {
|
|
382
|
+
stack.pop();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Stack is now empty
|
|
386
|
+
expect(stack.size).toBe(0);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('Depth-First Search (DFS)', () => {
|
|
282
390
|
const stack = new Stack<number>();
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
391
|
+
const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] };
|
|
392
|
+
const visited: number[] = [];
|
|
393
|
+
stack.push(1);
|
|
394
|
+
while (!stack.isEmpty()) {
|
|
395
|
+
const node = stack.pop()!;
|
|
396
|
+
if (!visited.includes(node)) {
|
|
397
|
+
visited.push(node);
|
|
398
|
+
graph[node].forEach(neighbor => stack.push(neighbor));
|
|
288
399
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
});
|
|
292
|
-
expect(spans).toEqual([1, 1, 1, 2, 1, 4, 6]);
|
|
400
|
+
}
|
|
401
|
+
expect(visited).toEqual([1, 3, 5, 2, 4]); // Example DFS order
|
|
293
402
|
});
|
|
294
403
|
|
|
295
404
|
it('Browser Navigation', () => {
|