red-black-tree-typed 2.2.2 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -37
- package/dist/cjs/index.cjs +163 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +164 -0
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +163 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +164 -0
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +96 -2
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
- package/dist/types/data-structures/binary-tree/bst.d.ts +156 -13
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +84 -35
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- 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/umd/red-black-tree-typed.js +164 -0
- package/dist/umd/red-black-tree-typed.js.map +1 -1
- package/dist/umd/red-black-tree-typed.min.js +3 -3
- package/dist/umd/red-black-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +96 -2
- package/src/data-structures/binary-tree/binary-tree.ts +117 -7
- package/src/data-structures/binary-tree/bst.ts +322 -13
- package/src/data-structures/binary-tree/red-black-tree.ts +84 -35
- package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
- 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
|
@@ -27,93 +27,121 @@ import { LinearBase } from '../base/linear-base';
|
|
|
27
27
|
* 4. Efficiency: Adding and removing elements at both ends of a deque is usually very fast. However, when the dynamic array needs to expand, it may involve copying the entire array to a larger one, and this operation has a time complexity of O(n).
|
|
28
28
|
* 5. Performance jitter: Deque may experience performance jitter, but DoublyLinkedList will not
|
|
29
29
|
* @example
|
|
30
|
-
* //
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* // basic Deque creation and push/pop operations
|
|
31
|
+
* // Create a simple Deque with initial values
|
|
32
|
+
* const deque = new Deque([1, 2, 3, 4, 5]);
|
|
33
33
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* this.deque = new Deque<string>(prizes);
|
|
37
|
-
* }
|
|
34
|
+
* // Verify the deque maintains insertion order
|
|
35
|
+
* console.log([...deque]); // [1, 2, 3, 4, 5];
|
|
38
36
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* const n = this.deque.length;
|
|
42
|
-
* if (n === 0) return;
|
|
37
|
+
* // Check length
|
|
38
|
+
* console.log(deque.length); // 5;
|
|
43
39
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* }
|
|
48
|
-
* }
|
|
40
|
+
* // Push to the end
|
|
41
|
+
* deque.push(6);
|
|
42
|
+
* console.log(deque.length); // 6;
|
|
49
43
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
44
|
+
* // Pop from the end
|
|
45
|
+
* const last = deque.pop();
|
|
46
|
+
* console.log(last); // 6;
|
|
47
|
+
* @example
|
|
48
|
+
* // Deque shift and unshift operations
|
|
49
|
+
* const deque = new Deque<number>([20, 30, 40]);
|
|
54
50
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* }
|
|
59
|
-
* }
|
|
51
|
+
* // Unshift adds to the front
|
|
52
|
+
* deque.unshift(10);
|
|
53
|
+
* console.log([...deque]); // [10, 20, 30, 40];
|
|
60
54
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* }
|
|
65
|
-
* }
|
|
55
|
+
* // Shift removes from the front (O(1) complexity!)
|
|
56
|
+
* const first = deque.shift();
|
|
57
|
+
* console.log(first); // 10;
|
|
66
58
|
*
|
|
67
|
-
* //
|
|
68
|
-
*
|
|
69
|
-
*
|
|
59
|
+
* // Verify remaining elements
|
|
60
|
+
* console.log([...deque]); // [20, 30, 40];
|
|
61
|
+
* console.log(deque.length); // 3;
|
|
62
|
+
* @example
|
|
63
|
+
* // Deque peek at both ends
|
|
64
|
+
* const deque = new Deque<number>([10, 20, 30, 40, 50]);
|
|
70
65
|
*
|
|
71
|
-
* //
|
|
72
|
-
*
|
|
66
|
+
* // Get first element without removing
|
|
67
|
+
* const first = deque.at(0);
|
|
68
|
+
* console.log(first); // 10;
|
|
73
69
|
*
|
|
74
|
-
* //
|
|
75
|
-
*
|
|
76
|
-
* console.log(
|
|
70
|
+
* // Get last element without removing
|
|
71
|
+
* const last = deque.at(deque.length - 1);
|
|
72
|
+
* console.log(last); // 50;
|
|
77
73
|
*
|
|
78
|
-
* //
|
|
79
|
-
*
|
|
80
|
-
* console.log(roulette.display()); // 'Headphones'
|
|
74
|
+
* // Length unchanged
|
|
75
|
+
* console.log(deque.length); // 5;
|
|
81
76
|
* @example
|
|
82
|
-
* //
|
|
83
|
-
*
|
|
84
|
-
* function maxSlidingWindow(nums: number[], k: number): number[] {
|
|
85
|
-
* const n = nums.length;
|
|
86
|
-
* if (n * k === 0) return [];
|
|
77
|
+
* // Deque for...of iteration and reverse
|
|
78
|
+
* const deque = new Deque<string>(['A', 'B', 'C', 'D']);
|
|
87
79
|
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
80
|
+
* // Iterate forward
|
|
81
|
+
* const forward: string[] = [];
|
|
82
|
+
* for (const item of deque) {
|
|
83
|
+
* forward.push(item);
|
|
84
|
+
* }
|
|
85
|
+
* console.log(forward); // ['A', 'B', 'C', 'D'];
|
|
90
86
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
87
|
+
* // Reverse the deque
|
|
88
|
+
* deque.reverse();
|
|
89
|
+
* const backward: string[] = [];
|
|
90
|
+
* for (const item of deque) {
|
|
91
|
+
* backward.push(item);
|
|
92
|
+
* }
|
|
93
|
+
* console.log(backward); // ['D', 'C', 'B', 'A'];
|
|
94
|
+
* @example
|
|
95
|
+
* // Deque as sliding window for stream processing
|
|
96
|
+
* interface DataPoint {
|
|
97
|
+
* timestamp: number;
|
|
98
|
+
* value: number;
|
|
99
|
+
* sensor: string;
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* // Create a deque-based sliding window for real-time data aggregation
|
|
103
|
+
* const windowSize = 3;
|
|
104
|
+
* const dataWindow = new Deque<DataPoint>();
|
|
96
105
|
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
106
|
+
* // Simulate incoming sensor data stream
|
|
107
|
+
* const incomingData: DataPoint[] = [
|
|
108
|
+
* { timestamp: 1000, value: 25.5, sensor: 'temp-01' },
|
|
109
|
+
* { timestamp: 1100, value: 26.2, sensor: 'temp-01' },
|
|
110
|
+
* { timestamp: 1200, value: 25.8, sensor: 'temp-01' },
|
|
111
|
+
* { timestamp: 1300, value: 27.1, sensor: 'temp-01' },
|
|
112
|
+
* { timestamp: 1400, value: 26.9, sensor: 'temp-01' }
|
|
113
|
+
* ];
|
|
101
114
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
115
|
+
* const windowResults: Array<{ avgValue: number; windowSize: number }> = [];
|
|
116
|
+
*
|
|
117
|
+
* for (const dataPoint of incomingData) {
|
|
118
|
+
* // Add new data to the end
|
|
119
|
+
* dataWindow.push(dataPoint);
|
|
120
|
+
*
|
|
121
|
+
* // Remove oldest data when window exceeds size (O(1) from front)
|
|
122
|
+
* if (dataWindow.length > windowSize) {
|
|
123
|
+
* dataWindow.shift();
|
|
124
|
+
* }
|
|
104
125
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
126
|
+
* // Calculate average of current window
|
|
127
|
+
* let sum = 0;
|
|
128
|
+
* for (const point of dataWindow) {
|
|
129
|
+
* sum += point.value;
|
|
109
130
|
* }
|
|
131
|
+
* const avg = sum / dataWindow.length;
|
|
110
132
|
*
|
|
111
|
-
*
|
|
133
|
+
* windowResults.push({
|
|
134
|
+
* avgValue: Math.round(avg * 10) / 10,
|
|
135
|
+
* windowSize: dataWindow.length
|
|
136
|
+
* });
|
|
112
137
|
* }
|
|
113
138
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* console.log(
|
|
139
|
+
* // Verify sliding window behavior
|
|
140
|
+
* console.log(windowResults.length); // 5;
|
|
141
|
+
* console.log(windowResults[0].windowSize); // 1; // First window has 1 element
|
|
142
|
+
* console.log(windowResults[2].windowSize); // 3; // Windows are at max size from 3rd onwards
|
|
143
|
+
* console.log(windowResults[4].windowSize); // 3; // Last window still has 3 elements
|
|
144
|
+
* console.log(dataWindow.length); // 3;
|
|
117
145
|
*/
|
|
118
146
|
export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
119
147
|
protected _equals: (a: E, b: E) => boolean = Object.is as unknown as (a: E, b: E) => boolean;
|
|
@@ -23,52 +23,108 @@ import { LinearBase } from '../base/linear-base';
|
|
|
23
23
|
* 6. Breadth-First Search (BFS): In traversal algorithms for graphs and trees, queues store elements that are to be visited.
|
|
24
24
|
* 7. Real-time Queuing: Like queuing systems in banks or supermarkets.
|
|
25
25
|
* @example
|
|
26
|
-
* //
|
|
27
|
-
*
|
|
28
|
-
* const
|
|
29
|
-
* const queue = new Queue<number>();
|
|
26
|
+
* // basic Queue creation and push operation
|
|
27
|
+
* // Create a simple Queue with initial values
|
|
28
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
30
29
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* // Verify the queue maintains insertion order
|
|
31
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
33
32
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
33
|
+
* // Check length
|
|
34
|
+
* console.log(queue.length); // 5;
|
|
35
|
+
* @example
|
|
36
|
+
* // Queue shift and peek operations
|
|
37
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
37
38
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* }
|
|
39
|
+
* // Peek at the front element without removing it
|
|
40
|
+
* console.log(queue.first); // 10;
|
|
41
41
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* });
|
|
42
|
+
* // Remove and get the first element (FIFO)
|
|
43
|
+
* const first = queue.shift();
|
|
44
|
+
* console.log(first); // 10;
|
|
46
45
|
*
|
|
47
|
-
*
|
|
46
|
+
* // Verify remaining elements and length decreased
|
|
47
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
48
|
+
* console.log(queue.length); // 3;
|
|
48
49
|
* @example
|
|
49
|
-
* //
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
50
|
+
* // Queue for...of iteration and isEmpty check
|
|
51
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
52
|
+
*
|
|
53
|
+
* const elements: string[] = [];
|
|
54
|
+
* for (const item of queue) {
|
|
55
|
+
* elements.push(item);
|
|
56
|
+
* }
|
|
57
|
+
*
|
|
58
|
+
* // Verify all elements are iterated in order
|
|
59
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
57
60
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
61
|
+
* // Process all elements
|
|
62
|
+
* while (queue.length > 0) {
|
|
63
|
+
* queue.shift();
|
|
64
|
+
* }
|
|
65
|
+
*
|
|
66
|
+
* console.log(queue.length); // 0;
|
|
67
|
+
* @example
|
|
68
|
+
* // Queue as message broker for event processing
|
|
69
|
+
* interface Message {
|
|
70
|
+
* id: string;
|
|
71
|
+
* type: 'email' | 'sms' | 'push';
|
|
72
|
+
* recipient: string;
|
|
73
|
+
* content: string;
|
|
74
|
+
* timestamp: Date;
|
|
75
|
+
* }
|
|
60
76
|
*
|
|
61
|
-
* queue
|
|
77
|
+
* // Create a message queue for real-time event processing
|
|
78
|
+
* const messageQueue = new Queue<Message>([
|
|
79
|
+
* {
|
|
80
|
+
* id: 'msg-001',
|
|
81
|
+
* type: 'email',
|
|
82
|
+
* recipient: 'user@example.com',
|
|
83
|
+
* content: 'Welcome!',
|
|
84
|
+
* timestamp: new Date()
|
|
85
|
+
* },
|
|
86
|
+
* {
|
|
87
|
+
* id: 'msg-002',
|
|
88
|
+
* type: 'sms',
|
|
89
|
+
* recipient: '+1234567890',
|
|
90
|
+
* content: 'OTP: 123456',
|
|
91
|
+
* timestamp: new Date()
|
|
92
|
+
* },
|
|
93
|
+
* {
|
|
94
|
+
* id: 'msg-003',
|
|
95
|
+
* type: 'push',
|
|
96
|
+
* recipient: 'device-token-xyz',
|
|
97
|
+
* content: 'New notification',
|
|
98
|
+
* timestamp: new Date()
|
|
99
|
+
* },
|
|
100
|
+
* {
|
|
101
|
+
* id: 'msg-004',
|
|
102
|
+
* type: 'email',
|
|
103
|
+
* recipient: 'admin@example.com',
|
|
104
|
+
* content: 'Daily report',
|
|
105
|
+
* timestamp: new Date()
|
|
106
|
+
* }
|
|
107
|
+
* ]);
|
|
62
108
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
109
|
+
* // Process messages in FIFO order (first message first)
|
|
110
|
+
* const processedMessages: string[] = [];
|
|
111
|
+
* while (messageQueue.length > 0) {
|
|
112
|
+
* const message = messageQueue.shift();
|
|
113
|
+
* if (message) {
|
|
114
|
+
* processedMessages.push(`${message.type}:${message.recipient}`);
|
|
68
115
|
* }
|
|
69
116
|
* }
|
|
70
117
|
*
|
|
71
|
-
*
|
|
118
|
+
* // Verify messages were processed in order
|
|
119
|
+
* console.log(processedMessages); // [
|
|
120
|
+
* // 'email:user@example.com',
|
|
121
|
+
* // 'sms:+1234567890',
|
|
122
|
+
* // 'push:device-token-xyz',
|
|
123
|
+
* // 'email:admin@example.com'
|
|
124
|
+
* // ];
|
|
125
|
+
*
|
|
126
|
+
* // Queue should be empty after processing all messages
|
|
127
|
+
* console.log(messageQueue.length); // 0;
|
|
72
128
|
*/
|
|
73
129
|
export class Queue<E = any, R = any> extends LinearBase<E, R> {
|
|
74
130
|
/**
|
|
@@ -21,8 +21,49 @@ import { IterableElementBase } from '../base';
|
|
|
21
21
|
* 5. Expression Evaluation: Used for the evaluation of arithmetic or logical expressions, especially when dealing with parenthesis matching and operator precedence.
|
|
22
22
|
* 6. Backtracking Algorithms: In problems where multiple branches need to be explored but only one branch can be explored at a time, stacks can be used to save the state at each branching point.
|
|
23
23
|
* @example
|
|
24
|
+
* // basic Stack creation and push operation
|
|
25
|
+
* // Create a simple Stack with initial values
|
|
26
|
+
* const stack = new Stack([1, 2, 3, 4, 5]);
|
|
27
|
+
*
|
|
28
|
+
* // Verify the stack maintains insertion order (LIFO will be shown in pop)
|
|
29
|
+
* console.log([...stack]); // [1, 2, 3, 4, 5];
|
|
30
|
+
*
|
|
31
|
+
* // Check length
|
|
32
|
+
* console.log(stack.size); // 5;
|
|
33
|
+
*
|
|
34
|
+
* // Push a new element to the top
|
|
35
|
+
* stack.push(6);
|
|
36
|
+
* console.log(stack.size); // 6;
|
|
37
|
+
* @example
|
|
38
|
+
* // Stack pop operation (LIFO - Last In First Out)
|
|
39
|
+
* const stack = new Stack<number>([10, 20, 30, 40, 50]);
|
|
40
|
+
*
|
|
41
|
+
* // Peek at the top element without removing
|
|
42
|
+
* const top = stack.peek();
|
|
43
|
+
* console.log(top); // 50;
|
|
44
|
+
*
|
|
45
|
+
* // Pop removes from the top (LIFO order)
|
|
46
|
+
* const popped = stack.pop();
|
|
47
|
+
* console.log(popped); // 50;
|
|
48
|
+
*
|
|
49
|
+
* // Next pop gets the previous element
|
|
50
|
+
* const next = stack.pop();
|
|
51
|
+
* console.log(next); // 40;
|
|
52
|
+
*
|
|
53
|
+
* // Verify length decreased
|
|
54
|
+
* console.log(stack.size); // 3;
|
|
55
|
+
* @example
|
|
56
|
+
* // Function Call Stack
|
|
57
|
+
* const functionStack = new Stack<string>();
|
|
58
|
+
* functionStack.push('main');
|
|
59
|
+
* functionStack.push('foo');
|
|
60
|
+
* functionStack.push('bar');
|
|
61
|
+
* console.log(functionStack.pop()); // 'bar';
|
|
62
|
+
* console.log(functionStack.pop()); // 'foo';
|
|
63
|
+
* console.log(functionStack.pop()); // 'main';
|
|
64
|
+
* @example
|
|
24
65
|
* // Balanced Parentheses or Brackets
|
|
25
|
-
*
|
|
66
|
+
* type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{';
|
|
26
67
|
*
|
|
27
68
|
* const stack = new Stack<string>();
|
|
28
69
|
* const input: ValidCharacters[] = '[({})]'.split('') as ValidCharacters[];
|
|
@@ -36,10 +77,10 @@ import { IterableElementBase } from '../base';
|
|
|
36
77
|
* }
|
|
37
78
|
* }
|
|
38
79
|
* }
|
|
39
|
-
* console.log(stack.isEmpty()); // true
|
|
80
|
+
* console.log(stack.isEmpty()); // true;
|
|
40
81
|
* @example
|
|
41
82
|
* // Expression Evaluation and Conversion
|
|
42
|
-
*
|
|
83
|
+
* const stack = new Stack<number>();
|
|
43
84
|
* const expression = [5, 3, '+']; // Equivalent to 5 + 3
|
|
44
85
|
* expression.forEach(token => {
|
|
45
86
|
* if (typeof token === 'number') {
|
|
@@ -50,24 +91,10 @@ import { IterableElementBase } from '../base';
|
|
|
50
91
|
* stack.push(token === '+' ? a + b : 0); // Only handling '+' here
|
|
51
92
|
* }
|
|
52
93
|
* });
|
|
53
|
-
* console.log(stack.pop()); // 8
|
|
54
|
-
* @example
|
|
55
|
-
* // Depth-First Search (DFS)
|
|
56
|
-
* const stack = new Stack<number>();
|
|
57
|
-
* const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] };
|
|
58
|
-
* const visited: number[] = [];
|
|
59
|
-
* stack.push(1);
|
|
60
|
-
* while (!stack.isEmpty()) {
|
|
61
|
-
* const node = stack.pop()!;
|
|
62
|
-
* if (!visited.includes(node)) {
|
|
63
|
-
* visited.push(node);
|
|
64
|
-
* graph[node].forEach(neighbor => stack.push(neighbor));
|
|
65
|
-
* }
|
|
66
|
-
* }
|
|
67
|
-
* console.log(visited); // [1, 3, 5, 2, 4]
|
|
94
|
+
* console.log(stack.pop()); // 8;
|
|
68
95
|
* @example
|
|
69
96
|
* // Backtracking Algorithms
|
|
70
|
-
*
|
|
97
|
+
* const stack = new Stack<[number, number]>();
|
|
71
98
|
* const maze = [
|
|
72
99
|
* ['S', ' ', 'X'],
|
|
73
100
|
* ['X', ' ', 'X'],
|
|
@@ -109,28 +136,10 @@ import { IterableElementBase } from '../base';
|
|
|
109
136
|
* }
|
|
110
137
|
* }
|
|
111
138
|
*
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* // Function Call Stack
|
|
115
|
-
* const functionStack = new Stack<string>();
|
|
116
|
-
* functionStack.push('main');
|
|
117
|
-
* functionStack.push('foo');
|
|
118
|
-
* functionStack.push('bar');
|
|
119
|
-
* console.log(functionStack.pop()); // 'bar'
|
|
120
|
-
* console.log(functionStack.pop()); // 'foo'
|
|
121
|
-
* console.log(functionStack.pop()); // 'main'
|
|
122
|
-
* @example
|
|
123
|
-
* // Simplify File Paths
|
|
124
|
-
* const stack = new Stack<string>();
|
|
125
|
-
* const path = '/a/./b/../../c';
|
|
126
|
-
* path.split('/').forEach(segment => {
|
|
127
|
-
* if (segment === '..') stack.pop();
|
|
128
|
-
* else if (segment && segment !== '.') stack.push(segment);
|
|
129
|
-
* });
|
|
130
|
-
* console.log(stack.elements.join('/')); // 'c'
|
|
139
|
+
* console.log(path); // contains end;
|
|
131
140
|
* @example
|
|
132
141
|
* // Stock Span Problem
|
|
133
|
-
*
|
|
142
|
+
* const stack = new Stack<number>();
|
|
134
143
|
* const prices = [100, 80, 60, 70, 60, 75, 85];
|
|
135
144
|
* const spans: number[] = [];
|
|
136
145
|
* prices.forEach((price, i) => {
|
|
@@ -140,7 +149,16 @@ import { IterableElementBase } from '../base';
|
|
|
140
149
|
* spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!);
|
|
141
150
|
* stack.push(i);
|
|
142
151
|
* });
|
|
143
|
-
* console.log(spans); // [1, 1, 1, 2, 1, 4, 6]
|
|
152
|
+
* console.log(spans); // [1, 1, 1, 2, 1, 4, 6];
|
|
153
|
+
* @example
|
|
154
|
+
* // Simplify File Paths
|
|
155
|
+
* const stack = new Stack<string>();
|
|
156
|
+
* const path = '/a/./b/../../c';
|
|
157
|
+
* path.split('/').forEach(segment => {
|
|
158
|
+
* if (segment === '..') stack.pop();
|
|
159
|
+
* else if (segment && segment !== '.') stack.push(segment);
|
|
160
|
+
* });
|
|
161
|
+
* console.log(stack.elements.join('/')); // 'c';
|
|
144
162
|
*/
|
|
145
163
|
export class Stack<E = any, R = any> extends IterableElementBase<E, R> {
|
|
146
164
|
protected _equals: (a: E, b: E) => boolean = Object.is as unknown as (a: E, b: E) => boolean;
|