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.
Files changed (46) hide show
  1. package/README.md +92 -37
  2. package/dist/cjs/index.cjs +163 -0
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs-legacy/index.cjs +164 -0
  5. package/dist/cjs-legacy/index.cjs.map +1 -1
  6. package/dist/esm/index.mjs +163 -0
  7. package/dist/esm/index.mjs.map +1 -1
  8. package/dist/esm-legacy/index.mjs +164 -0
  9. package/dist/esm-legacy/index.mjs.map +1 -1
  10. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +96 -2
  11. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
  12. package/dist/types/data-structures/binary-tree/bst.d.ts +156 -13
  13. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +84 -35
  14. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
  15. package/dist/types/data-structures/graph/directed-graph.d.ts +126 -1
  16. package/dist/types/data-structures/graph/undirected-graph.d.ts +160 -1
  17. package/dist/types/data-structures/hash/hash-map.d.ts +110 -27
  18. package/dist/types/data-structures/heap/heap.d.ts +107 -58
  19. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +72 -404
  20. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -5
  21. package/dist/types/data-structures/queue/deque.d.ts +95 -67
  22. package/dist/types/data-structures/queue/queue.d.ts +90 -34
  23. package/dist/types/data-structures/stack/stack.d.ts +58 -40
  24. package/dist/types/data-structures/trie/trie.d.ts +109 -47
  25. package/dist/types/interfaces/binary-tree.d.ts +1 -0
  26. package/dist/umd/red-black-tree-typed.js +164 -0
  27. package/dist/umd/red-black-tree-typed.js.map +1 -1
  28. package/dist/umd/red-black-tree-typed.min.js +3 -3
  29. package/dist/umd/red-black-tree-typed.min.js.map +1 -1
  30. package/package.json +2 -2
  31. package/src/data-structures/binary-tree/avl-tree.ts +96 -2
  32. package/src/data-structures/binary-tree/binary-tree.ts +117 -7
  33. package/src/data-structures/binary-tree/bst.ts +322 -13
  34. package/src/data-structures/binary-tree/red-black-tree.ts +84 -35
  35. package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
  36. package/src/data-structures/graph/directed-graph.ts +126 -1
  37. package/src/data-structures/graph/undirected-graph.ts +160 -1
  38. package/src/data-structures/hash/hash-map.ts +110 -27
  39. package/src/data-structures/heap/heap.ts +107 -58
  40. package/src/data-structures/linked-list/doubly-linked-list.ts +72 -404
  41. package/src/data-structures/linked-list/singly-linked-list.ts +121 -5
  42. package/src/data-structures/queue/deque.ts +95 -67
  43. package/src/data-structures/queue/queue.ts +90 -34
  44. package/src/data-structures/stack/stack.ts +58 -40
  45. package/src/data-structures/trie/trie.ts +109 -47
  46. package/src/interfaces/binary-tree.ts +2 -0
@@ -18,93 +18,121 @@ import { LinearBase } from '../base/linear-base';
18
18
  * 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).
19
19
  * 5. Performance jitter: Deque may experience performance jitter, but DoublyLinkedList will not
20
20
  * @example
21
- * // prize roulette
22
- * class PrizeRoulette {
23
- * private deque: Deque<string>;
21
+ * // basic Deque creation and push/pop operations
22
+ * // Create a simple Deque with initial values
23
+ * const deque = new Deque([1, 2, 3, 4, 5]);
24
24
  *
25
- * constructor(prizes: string[]) {
26
- * // Initialize the deque with prizes
27
- * this.deque = new Deque<string>(prizes);
28
- * }
25
+ * // Verify the deque maintains insertion order
26
+ * console.log([...deque]); // [1, 2, 3, 4, 5];
29
27
  *
30
- * // Rotate clockwise to the right (forward)
31
- * rotateClockwise(steps: number): void {
32
- * const n = this.deque.length;
33
- * if (n === 0) return;
28
+ * // Check length
29
+ * console.log(deque.length); // 5;
34
30
  *
35
- * for (let i = 0; i < steps; i++) {
36
- * const last = this.deque.pop(); // Remove the last element
37
- * this.deque.unshift(last!); // Add it to the front
38
- * }
39
- * }
31
+ * // Push to the end
32
+ * deque.push(6);
33
+ * console.log(deque.length); // 6;
40
34
  *
41
- * // Rotate counterclockwise to the left (backward)
42
- * rotateCounterClockwise(steps: number): void {
43
- * const n = this.deque.length;
44
- * if (n === 0) return;
35
+ * // Pop from the end
36
+ * const last = deque.pop();
37
+ * console.log(last); // 6;
38
+ * @example
39
+ * // Deque shift and unshift operations
40
+ * const deque = new Deque<number>([20, 30, 40]);
45
41
  *
46
- * for (let i = 0; i < steps; i++) {
47
- * const first = this.deque.shift(); // Remove the first element
48
- * this.deque.push(first!); // Add it to the back
49
- * }
50
- * }
42
+ * // Unshift adds to the front
43
+ * deque.unshift(10);
44
+ * console.log([...deque]); // [10, 20, 30, 40];
51
45
  *
52
- * // Display the current prize at the head
53
- * display() {
54
- * return this.deque.first;
55
- * }
56
- * }
46
+ * // Shift removes from the front (O(1) complexity!)
47
+ * const first = deque.shift();
48
+ * console.log(first); // 10;
57
49
  *
58
- * // Example usage
59
- * const prizes = ['Car', 'Bike', 'Laptop', 'Phone', 'Watch', 'Headphones']; // Initialize the prize list
60
- * const roulette = new PrizeRoulette(prizes);
50
+ * // Verify remaining elements
51
+ * console.log([...deque]); // [20, 30, 40];
52
+ * console.log(deque.length); // 3;
53
+ * @example
54
+ * // Deque peek at both ends
55
+ * const deque = new Deque<number>([10, 20, 30, 40, 50]);
61
56
  *
62
- * // Display the initial state
63
- * console.log(roulette.display()); // 'Car' // Car
57
+ * // Get first element without removing
58
+ * const first = deque.at(0);
59
+ * console.log(first); // 10;
64
60
  *
65
- * // Rotate clockwise by 3 steps
66
- * roulette.rotateClockwise(3);
67
- * console.log(roulette.display()); // 'Phone' // Phone
61
+ * // Get last element without removing
62
+ * const last = deque.at(deque.length - 1);
63
+ * console.log(last); // 50;
68
64
  *
69
- * // Rotate counterclockwise by 2 steps
70
- * roulette.rotateCounterClockwise(2);
71
- * console.log(roulette.display()); // 'Headphones'
65
+ * // Length unchanged
66
+ * console.log(deque.length); // 5;
72
67
  * @example
73
- * // sliding window
74
- * // Maximum function of sliding window
75
- * function maxSlidingWindow(nums: number[], k: number): number[] {
76
- * const n = nums.length;
77
- * if (n * k === 0) return [];
68
+ * // Deque for...of iteration and reverse
69
+ * const deque = new Deque<string>(['A', 'B', 'C', 'D']);
78
70
  *
79
- * const deq = new Deque<number>();
80
- * const result: number[] = [];
71
+ * // Iterate forward
72
+ * const forward: string[] = [];
73
+ * for (const item of deque) {
74
+ * forward.push(item);
75
+ * }
76
+ * console.log(forward); // ['A', 'B', 'C', 'D'];
81
77
  *
82
- * for (let i = 0; i < n; i++) {
83
- * // Delete indexes in the queue that are not within the window range
84
- * if (deq.length > 0 && deq.first! === i - k) {
85
- * deq.shift();
86
- * }
78
+ * // Reverse the deque
79
+ * deque.reverse();
80
+ * const backward: string[] = [];
81
+ * for (const item of deque) {
82
+ * backward.push(item);
83
+ * }
84
+ * console.log(backward); // ['D', 'C', 'B', 'A'];
85
+ * @example
86
+ * // Deque as sliding window for stream processing
87
+ * interface DataPoint {
88
+ * timestamp: number;
89
+ * value: number;
90
+ * sensor: string;
91
+ * }
92
+ *
93
+ * // Create a deque-based sliding window for real-time data aggregation
94
+ * const windowSize = 3;
95
+ * const dataWindow = new Deque<DataPoint>();
87
96
  *
88
- * // Remove all indices less than the current value from the tail of the queue
89
- * while (deq.length > 0 && nums[deq.last!] < nums[i]) {
90
- * deq.pop();
91
- * }
97
+ * // Simulate incoming sensor data stream
98
+ * const incomingData: DataPoint[] = [
99
+ * { timestamp: 1000, value: 25.5, sensor: 'temp-01' },
100
+ * { timestamp: 1100, value: 26.2, sensor: 'temp-01' },
101
+ * { timestamp: 1200, value: 25.8, sensor: 'temp-01' },
102
+ * { timestamp: 1300, value: 27.1, sensor: 'temp-01' },
103
+ * { timestamp: 1400, value: 26.9, sensor: 'temp-01' }
104
+ * ];
92
105
  *
93
- * // Add the current index to the end of the queue
94
- * deq.push(i);
106
+ * const windowResults: Array<{ avgValue: number; windowSize: number }> = [];
107
+ *
108
+ * for (const dataPoint of incomingData) {
109
+ * // Add new data to the end
110
+ * dataWindow.push(dataPoint);
111
+ *
112
+ * // Remove oldest data when window exceeds size (O(1) from front)
113
+ * if (dataWindow.length > windowSize) {
114
+ * dataWindow.shift();
115
+ * }
95
116
  *
96
- * // Add the maximum value of the window to the results
97
- * if (i >= k - 1) {
98
- * result.push(nums[deq.first!]);
99
- * }
117
+ * // Calculate average of current window
118
+ * let sum = 0;
119
+ * for (const point of dataWindow) {
120
+ * sum += point.value;
100
121
  * }
122
+ * const avg = sum / dataWindow.length;
101
123
  *
102
- * return result;
124
+ * windowResults.push({
125
+ * avgValue: Math.round(avg * 10) / 10,
126
+ * windowSize: dataWindow.length
127
+ * });
103
128
  * }
104
129
  *
105
- * const nums = [1, 3, -1, -3, 5, 3, 6, 7];
106
- * const k = 3;
107
- * console.log(maxSlidingWindow(nums, k)); // [3, 3, 5, 5, 6, 7]
130
+ * // Verify sliding window behavior
131
+ * console.log(windowResults.length); // 5;
132
+ * console.log(windowResults[0].windowSize); // 1; // First window has 1 element
133
+ * console.log(windowResults[2].windowSize); // 3; // Windows are at max size from 3rd onwards
134
+ * console.log(windowResults[4].windowSize); // 3; // Last window still has 3 elements
135
+ * console.log(dataWindow.length); // 3;
108
136
  */
109
137
  export declare class Deque<E = any, R = any> extends LinearBase<E, R> {
110
138
  protected _equals: (a: E, b: E) => boolean;
@@ -21,52 +21,108 @@ import { LinearBase } from '../base/linear-base';
21
21
  * 6. Breadth-First Search (BFS): In traversal algorithms for graphs and trees, queues store elements that are to be visited.
22
22
  * 7. Real-time Queuing: Like queuing systems in banks or supermarkets.
23
23
  * @example
24
- * // Sliding Window using Queue
25
- * const nums = [2, 3, 4, 1, 5];
26
- * const k = 2;
27
- * const queue = new Queue<number>();
24
+ * // basic Queue creation and push operation
25
+ * // Create a simple Queue with initial values
26
+ * const queue = new Queue([1, 2, 3, 4, 5]);
28
27
  *
29
- * let maxSum = 0;
30
- * let currentSum = 0;
28
+ * // Verify the queue maintains insertion order
29
+ * console.log([...queue]); // [1, 2, 3, 4, 5];
31
30
  *
32
- * nums.forEach(num => {
33
- * queue.push(num);
34
- * currentSum += num;
31
+ * // Check length
32
+ * console.log(queue.length); // 5;
33
+ * @example
34
+ * // Queue shift and peek operations
35
+ * const queue = new Queue<number>([10, 20, 30, 40]);
35
36
  *
36
- * if (queue.length > k) {
37
- * currentSum -= queue.shift()!;
38
- * }
37
+ * // Peek at the front element without removing it
38
+ * console.log(queue.first); // 10;
39
39
  *
40
- * if (queue.length === k) {
41
- * maxSum = Math.max(maxSum, currentSum);
42
- * }
43
- * });
40
+ * // Remove and get the first element (FIFO)
41
+ * const first = queue.shift();
42
+ * console.log(first); // 10;
44
43
  *
45
- * console.log(maxSum); // 7
44
+ * // Verify remaining elements and length decreased
45
+ * console.log([...queue]); // [20, 30, 40];
46
+ * console.log(queue.length); // 3;
46
47
  * @example
47
- * // Breadth-First Search (BFS) using Queue
48
- * const graph: { [key in number]: number[] } = {
49
- * 1: [2, 3],
50
- * 2: [4, 5],
51
- * 3: [],
52
- * 4: [],
53
- * 5: []
54
- * };
48
+ * // Queue for...of iteration and isEmpty check
49
+ * const queue = new Queue<string>(['A', 'B', 'C', 'D']);
50
+ *
51
+ * const elements: string[] = [];
52
+ * for (const item of queue) {
53
+ * elements.push(item);
54
+ * }
55
+ *
56
+ * // Verify all elements are iterated in order
57
+ * console.log(elements); // ['A', 'B', 'C', 'D'];
55
58
  *
56
- * const queue = new Queue<number>();
57
- * const visited: number[] = [];
59
+ * // Process all elements
60
+ * while (queue.length > 0) {
61
+ * queue.shift();
62
+ * }
63
+ *
64
+ * console.log(queue.length); // 0;
65
+ * @example
66
+ * // Queue as message broker for event processing
67
+ * interface Message {
68
+ * id: string;
69
+ * type: 'email' | 'sms' | 'push';
70
+ * recipient: string;
71
+ * content: string;
72
+ * timestamp: Date;
73
+ * }
58
74
  *
59
- * queue.push(1);
75
+ * // Create a message queue for real-time event processing
76
+ * const messageQueue = new Queue<Message>([
77
+ * {
78
+ * id: 'msg-001',
79
+ * type: 'email',
80
+ * recipient: 'user@example.com',
81
+ * content: 'Welcome!',
82
+ * timestamp: new Date()
83
+ * },
84
+ * {
85
+ * id: 'msg-002',
86
+ * type: 'sms',
87
+ * recipient: '+1234567890',
88
+ * content: 'OTP: 123456',
89
+ * timestamp: new Date()
90
+ * },
91
+ * {
92
+ * id: 'msg-003',
93
+ * type: 'push',
94
+ * recipient: 'device-token-xyz',
95
+ * content: 'New notification',
96
+ * timestamp: new Date()
97
+ * },
98
+ * {
99
+ * id: 'msg-004',
100
+ * type: 'email',
101
+ * recipient: 'admin@example.com',
102
+ * content: 'Daily report',
103
+ * timestamp: new Date()
104
+ * }
105
+ * ]);
60
106
  *
61
- * while (!queue.isEmpty()) {
62
- * const node = queue.shift()!;
63
- * if (!visited.includes(node)) {
64
- * visited.push(node);
65
- * graph[node].forEach(neighbor => queue.push(neighbor));
107
+ * // Process messages in FIFO order (first message first)
108
+ * const processedMessages: string[] = [];
109
+ * while (messageQueue.length > 0) {
110
+ * const message = messageQueue.shift();
111
+ * if (message) {
112
+ * processedMessages.push(`${message.type}:${message.recipient}`);
66
113
  * }
67
114
  * }
68
115
  *
69
- * console.log(visited); // [1, 2, 3, 4, 5]
116
+ * // Verify messages were processed in order
117
+ * console.log(processedMessages); // [
118
+ * // 'email:user@example.com',
119
+ * // 'sms:+1234567890',
120
+ * // 'push:device-token-xyz',
121
+ * // 'email:admin@example.com'
122
+ * // ];
123
+ *
124
+ * // Queue should be empty after processing all messages
125
+ * console.log(messageQueue.length); // 0;
70
126
  */
71
127
  export declare class Queue<E = any, R = any> extends LinearBase<E, R> {
72
128
  /**
@@ -19,8 +19,49 @@ import { IterableElementBase } from '../base';
19
19
  * 5. Expression Evaluation: Used for the evaluation of arithmetic or logical expressions, especially when dealing with parenthesis matching and operator precedence.
20
20
  * 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.
21
21
  * @example
22
+ * // basic Stack creation and push operation
23
+ * // Create a simple Stack with initial values
24
+ * const stack = new Stack([1, 2, 3, 4, 5]);
25
+ *
26
+ * // Verify the stack maintains insertion order (LIFO will be shown in pop)
27
+ * console.log([...stack]); // [1, 2, 3, 4, 5];
28
+ *
29
+ * // Check length
30
+ * console.log(stack.size); // 5;
31
+ *
32
+ * // Push a new element to the top
33
+ * stack.push(6);
34
+ * console.log(stack.size); // 6;
35
+ * @example
36
+ * // Stack pop operation (LIFO - Last In First Out)
37
+ * const stack = new Stack<number>([10, 20, 30, 40, 50]);
38
+ *
39
+ * // Peek at the top element without removing
40
+ * const top = stack.peek();
41
+ * console.log(top); // 50;
42
+ *
43
+ * // Pop removes from the top (LIFO order)
44
+ * const popped = stack.pop();
45
+ * console.log(popped); // 50;
46
+ *
47
+ * // Next pop gets the previous element
48
+ * const next = stack.pop();
49
+ * console.log(next); // 40;
50
+ *
51
+ * // Verify length decreased
52
+ * console.log(stack.size); // 3;
53
+ * @example
54
+ * // Function Call Stack
55
+ * const functionStack = new Stack<string>();
56
+ * functionStack.push('main');
57
+ * functionStack.push('foo');
58
+ * functionStack.push('bar');
59
+ * console.log(functionStack.pop()); // 'bar';
60
+ * console.log(functionStack.pop()); // 'foo';
61
+ * console.log(functionStack.pop()); // 'main';
62
+ * @example
22
63
  * // Balanced Parentheses or Brackets
23
- * type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{';
64
+ * type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{';
24
65
  *
25
66
  * const stack = new Stack<string>();
26
67
  * const input: ValidCharacters[] = '[({})]'.split('') as ValidCharacters[];
@@ -34,10 +75,10 @@ import { IterableElementBase } from '../base';
34
75
  * }
35
76
  * }
36
77
  * }
37
- * console.log(stack.isEmpty()); // true
78
+ * console.log(stack.isEmpty()); // true;
38
79
  * @example
39
80
  * // Expression Evaluation and Conversion
40
- * const stack = new Stack<number>();
81
+ * const stack = new Stack<number>();
41
82
  * const expression = [5, 3, '+']; // Equivalent to 5 + 3
42
83
  * expression.forEach(token => {
43
84
  * if (typeof token === 'number') {
@@ -48,24 +89,10 @@ import { IterableElementBase } from '../base';
48
89
  * stack.push(token === '+' ? a + b : 0); // Only handling '+' here
49
90
  * }
50
91
  * });
51
- * console.log(stack.pop()); // 8
52
- * @example
53
- * // Depth-First Search (DFS)
54
- * const stack = new Stack<number>();
55
- * const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] };
56
- * const visited: number[] = [];
57
- * stack.push(1);
58
- * while (!stack.isEmpty()) {
59
- * const node = stack.pop()!;
60
- * if (!visited.includes(node)) {
61
- * visited.push(node);
62
- * graph[node].forEach(neighbor => stack.push(neighbor));
63
- * }
64
- * }
65
- * console.log(visited); // [1, 3, 5, 2, 4]
92
+ * console.log(stack.pop()); // 8;
66
93
  * @example
67
94
  * // Backtracking Algorithms
68
- * const stack = new Stack<[number, number]>();
95
+ * const stack = new Stack<[number, number]>();
69
96
  * const maze = [
70
97
  * ['S', ' ', 'X'],
71
98
  * ['X', ' ', 'X'],
@@ -107,28 +134,10 @@ import { IterableElementBase } from '../base';
107
134
  * }
108
135
  * }
109
136
  *
110
- * expect(path).toContainEqual(end);
111
- * @example
112
- * // Function Call Stack
113
- * const functionStack = new Stack<string>();
114
- * functionStack.push('main');
115
- * functionStack.push('foo');
116
- * functionStack.push('bar');
117
- * console.log(functionStack.pop()); // 'bar'
118
- * console.log(functionStack.pop()); // 'foo'
119
- * console.log(functionStack.pop()); // 'main'
120
- * @example
121
- * // Simplify File Paths
122
- * const stack = new Stack<string>();
123
- * const path = '/a/./b/../../c';
124
- * path.split('/').forEach(segment => {
125
- * if (segment === '..') stack.pop();
126
- * else if (segment && segment !== '.') stack.push(segment);
127
- * });
128
- * console.log(stack.elements.join('/')); // 'c'
137
+ * console.log(path); // contains end;
129
138
  * @example
130
139
  * // Stock Span Problem
131
- * const stack = new Stack<number>();
140
+ * const stack = new Stack<number>();
132
141
  * const prices = [100, 80, 60, 70, 60, 75, 85];
133
142
  * const spans: number[] = [];
134
143
  * prices.forEach((price, i) => {
@@ -138,7 +147,16 @@ import { IterableElementBase } from '../base';
138
147
  * spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!);
139
148
  * stack.push(i);
140
149
  * });
141
- * console.log(spans); // [1, 1, 1, 2, 1, 4, 6]
150
+ * console.log(spans); // [1, 1, 1, 2, 1, 4, 6];
151
+ * @example
152
+ * // Simplify File Paths
153
+ * const stack = new Stack<string>();
154
+ * const path = '/a/./b/../../c';
155
+ * path.split('/').forEach(segment => {
156
+ * if (segment === '..') stack.pop();
157
+ * else if (segment && segment !== '.') stack.push(segment);
158
+ * });
159
+ * console.log(stack.elements.join('/')); // 'c';
142
160
  */
143
161
  export declare class Stack<E = any, R = any> extends IterableElementBase<E, R> {
144
162
  protected _equals: (a: E, b: E) => boolean;