deque-typed 1.54.3 → 2.0.1
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 +91 -0
- package/dist/data-structures/base/iterable-element-base.d.ts +14 -40
- package/dist/data-structures/base/iterable-element-base.js +14 -11
- package/dist/data-structures/base/linear-base.d.ts +277 -0
- package/dist/data-structures/base/linear-base.js +552 -0
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +12 -8
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +50 -37
- package/dist/data-structures/binary-tree/avl-tree.d.ts +64 -0
- package/dist/data-structures/binary-tree/avl-tree.js +64 -0
- package/dist/data-structures/binary-tree/binary-tree.js +5 -5
- package/dist/data-structures/binary-tree/bst.js +11 -11
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +175 -14
- package/dist/data-structures/binary-tree/tree-multi-map.js +210 -40
- package/dist/data-structures/graph/abstract-graph.js +16 -16
- package/dist/data-structures/hash/hash-map.d.ts +46 -0
- package/dist/data-structures/hash/hash-map.js +46 -0
- package/dist/data-structures/heap/heap.d.ts +3 -11
- package/dist/data-structures/heap/heap.js +0 -10
- package/dist/data-structures/heap/max-heap.d.ts +2 -2
- package/dist/data-structures/heap/min-heap.d.ts +2 -2
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +65 -94
- package/dist/data-structures/linked-list/doubly-linked-list.js +131 -146
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +145 -75
- package/dist/data-structures/linked-list/singly-linked-list.js +283 -169
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +2 -2
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +2 -2
- package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -2
- package/dist/data-structures/queue/deque.d.ts +130 -91
- package/dist/data-structures/queue/deque.js +269 -169
- package/dist/data-structures/queue/queue.d.ts +131 -40
- package/dist/data-structures/queue/queue.js +181 -50
- package/dist/data-structures/stack/stack.d.ts +124 -11
- package/dist/data-structures/stack/stack.js +121 -10
- package/dist/data-structures/trie/trie.d.ts +4 -3
- package/dist/data-structures/trie/trie.js +3 -0
- package/dist/types/data-structures/base/base.d.ts +9 -4
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1 -1
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +2 -2
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +2 -2
- package/dist/types/data-structures/queue/deque.d.ts +2 -3
- package/dist/types/data-structures/queue/queue.d.ts +2 -2
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +29 -20
- package/src/data-structures/base/linear-base.ts +649 -0
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +51 -36
- package/src/data-structures/binary-tree/avl-tree.ts +64 -0
- package/src/data-structures/binary-tree/binary-tree.ts +5 -5
- package/src/data-structures/binary-tree/bst.ts +9 -9
- package/src/data-structures/binary-tree/tree-multi-map.ts +214 -40
- package/src/data-structures/graph/abstract-graph.ts +16 -16
- package/src/data-structures/hash/hash-map.ts +46 -0
- package/src/data-structures/heap/heap.ts +3 -14
- package/src/data-structures/heap/max-heap.ts +2 -2
- package/src/data-structures/heap/min-heap.ts +2 -2
- package/src/data-structures/linked-list/doubly-linked-list.ts +144 -160
- package/src/data-structures/linked-list/singly-linked-list.ts +307 -185
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -5
- package/src/data-structures/priority-queue/min-priority-queue.ts +2 -5
- package/src/data-structures/priority-queue/priority-queue.ts +2 -2
- package/src/data-structures/queue/deque.ts +286 -183
- package/src/data-structures/queue/queue.ts +196 -63
- package/src/data-structures/stack/stack.ts +124 -18
- package/src/data-structures/trie/trie.ts +7 -3
- package/src/types/data-structures/base/base.ts +17 -8
- package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +1 -1
- package/src/types/data-structures/binary-tree/tree-multi-map.ts +1 -1
- package/src/types/data-structures/linked-list/doubly-linked-list.ts +2 -2
- package/src/types/data-structures/linked-list/singly-linked-list.ts +2 -2
- package/src/types/data-structures/queue/deque.ts +2 -3
- package/src/types/data-structures/queue/queue.ts +2 -2
|
@@ -6,117 +6,142 @@
|
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
8
|
import type { ElementCallback, SinglyLinkedListOptions } from '../../types';
|
|
9
|
-
import {
|
|
9
|
+
import { LinearLinkedBase, LinkedListNode } from '../base/linear-base';
|
|
10
10
|
|
|
11
|
-
export class SinglyLinkedListNode<E = any> {
|
|
11
|
+
export class SinglyLinkedListNode<E = any> extends LinkedListNode<E> {
|
|
12
12
|
/**
|
|
13
13
|
* The constructor function initializes an instance of a class with a given value and sets the next property to undefined.
|
|
14
14
|
* @param {E} value - The "value" parameter is of type E, which means it can be any data type. It represents the value that
|
|
15
15
|
* will be stored in the node of a linked list.
|
|
16
16
|
*/
|
|
17
17
|
constructor(value: E) {
|
|
18
|
+
super(value);
|
|
18
19
|
this._value = value;
|
|
19
20
|
this._next = undefined;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
protected
|
|
23
|
+
protected override _next: SinglyLinkedListNode<E> | undefined;
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
* The function returns the value of a protected variable.
|
|
26
|
-
* @returns The value of the variable `_value` is being returned.
|
|
27
|
-
*/
|
|
28
|
-
get value(): E {
|
|
29
|
-
return this._value;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The above function sets the value of a variable.
|
|
34
|
-
* @param {E} value - The parameter "value" is of type E, which means it can be any type.
|
|
35
|
-
*/
|
|
36
|
-
set value(value: E) {
|
|
37
|
-
this._value = value;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
protected _next: SinglyLinkedListNode<E> | undefined;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* The `next` function returns the next node in a singly linked list.
|
|
44
|
-
* @returns The `next` property is being returned. It can be either a `SinglyLinkedListNode<E>`
|
|
45
|
-
* object or `undefined`.
|
|
46
|
-
*/
|
|
47
|
-
get next(): SinglyLinkedListNode<E> | undefined {
|
|
25
|
+
override get next(): SinglyLinkedListNode<E> | undefined {
|
|
48
26
|
return this._next;
|
|
49
27
|
}
|
|
50
28
|
|
|
51
|
-
|
|
52
|
-
* The "next" property of a SinglyLinkedListNode is set to the provided value.
|
|
53
|
-
* @param {SinglyLinkedListNode<E> | undefined} value - The `value` parameter is of type
|
|
54
|
-
* `SinglyLinkedListNode<E> | undefined`. This means that it can accept either a
|
|
55
|
-
* `SinglyLinkedListNode` object or `undefined` as its value.
|
|
56
|
-
*/
|
|
57
|
-
set next(value: SinglyLinkedListNode<E> | undefined) {
|
|
29
|
+
override set next(value: SinglyLinkedListNode<E> | undefined) {
|
|
58
30
|
this._next = value;
|
|
59
31
|
}
|
|
60
32
|
}
|
|
61
33
|
|
|
62
34
|
/**
|
|
35
|
+
* 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.
|
|
36
|
+
* 2. Bidirectional Traversal: Unlike doubly linked lists, singly linked lists can be easily traversed forwards but not backwards.
|
|
37
|
+
* 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.
|
|
38
|
+
* 4. High Efficiency in Insertion and Deletion: Adding or removing elements in a linked list does not require moving other elements, making these operations more efficient than in arrays.
|
|
39
|
+
* Caution: Although our linked list classes provide methods such as at, setAt, addAt, and indexOf that are based on array indices, their time complexity, like that of the native Array.lastIndexOf, is 𝑂(𝑛). If you need to use these methods frequently, you might want to consider other data structures, such as Deque or Queue (designed for random access). Similarly, since the native Array.shift method has a time complexity of 𝑂(𝑛), using an array to simulate a queue can be inefficient. In such cases, you should use Queue or Deque, as these data structures leverage deferred array rearrangement, effectively reducing the average time complexity to 𝑂(1).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // implementation of a basic text editor
|
|
43
|
+
* class TextEditor {
|
|
44
|
+
* private content: SinglyLinkedList<string>;
|
|
45
|
+
* private cursorIndex: number;
|
|
46
|
+
* private undoStack: Stack<{ operation: string; data?: any }>;
|
|
47
|
+
*
|
|
48
|
+
* constructor() {
|
|
49
|
+
* this.content = new SinglyLinkedList<string>();
|
|
50
|
+
* this.cursorIndex = 0; // Cursor starts at the beginning
|
|
51
|
+
* this.undoStack = new Stack<{ operation: string; data?: any }>(); // Stack to keep track of operations for undo
|
|
52
|
+
* }
|
|
53
|
+
*
|
|
54
|
+
* insert(char: string) {
|
|
55
|
+
* this.content.addAt(this.cursorIndex, char);
|
|
56
|
+
* this.cursorIndex++;
|
|
57
|
+
* this.undoStack.push({ operation: 'insert', data: { index: this.cursorIndex - 1 } });
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* delete() {
|
|
61
|
+
* if (this.cursorIndex === 0) return; // Nothing to delete
|
|
62
|
+
* const deleted = this.content.deleteAt(this.cursorIndex - 1);
|
|
63
|
+
* this.cursorIndex--;
|
|
64
|
+
* this.undoStack.push({ operation: 'delete', data: { index: this.cursorIndex, char: deleted } });
|
|
65
|
+
* }
|
|
66
|
+
*
|
|
67
|
+
* moveCursor(index: number) {
|
|
68
|
+
* this.cursorIndex = Math.max(0, Math.min(index, this.content.length));
|
|
69
|
+
* }
|
|
70
|
+
*
|
|
71
|
+
* undo() {
|
|
72
|
+
* if (this.undoStack.size === 0) return; // No operations to undo
|
|
73
|
+
* const lastAction = this.undoStack.pop();
|
|
63
74
|
*
|
|
75
|
+
* if (lastAction!.operation === 'insert') {
|
|
76
|
+
* this.content.deleteAt(lastAction!.data.index);
|
|
77
|
+
* this.cursorIndex = lastAction!.data.index;
|
|
78
|
+
* } else if (lastAction!.operation === 'delete') {
|
|
79
|
+
* this.content.addAt(lastAction!.data.index, lastAction!.data.char);
|
|
80
|
+
* this.cursorIndex = lastAction!.data.index + 1;
|
|
81
|
+
* }
|
|
82
|
+
* }
|
|
83
|
+
*
|
|
84
|
+
* getText(): string {
|
|
85
|
+
* return [...this.content].join('');
|
|
86
|
+
* }
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* // Example Usage
|
|
90
|
+
* const editor = new TextEditor();
|
|
91
|
+
* editor.insert('H');
|
|
92
|
+
* editor.insert('e');
|
|
93
|
+
* editor.insert('l');
|
|
94
|
+
* editor.insert('l');
|
|
95
|
+
* editor.insert('o');
|
|
96
|
+
* console.log(editor.getText()); // 'Hello' // Output: "Hello"
|
|
97
|
+
*
|
|
98
|
+
* editor.delete();
|
|
99
|
+
* console.log(editor.getText()); // 'Hell' // Output: "Hell"
|
|
100
|
+
*
|
|
101
|
+
* editor.undo();
|
|
102
|
+
* console.log(editor.getText()); // 'Hello' // Output: "Hello"
|
|
103
|
+
*
|
|
104
|
+
* editor.moveCursor(1);
|
|
105
|
+
* editor.insert('a');
|
|
106
|
+
* console.log(editor.getText()); // 'Haello'
|
|
64
107
|
*/
|
|
65
|
-
export class SinglyLinkedList<E = any, R = any> extends
|
|
108
|
+
export class SinglyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, SinglyLinkedListNode<E>> {
|
|
66
109
|
constructor(
|
|
67
110
|
elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>> = [],
|
|
68
111
|
options?: SinglyLinkedListOptions<E, R>
|
|
69
112
|
) {
|
|
70
113
|
super(options);
|
|
114
|
+
|
|
115
|
+
if (options) {
|
|
116
|
+
}
|
|
117
|
+
|
|
71
118
|
this.pushMany(elements);
|
|
72
119
|
}
|
|
73
120
|
|
|
74
121
|
protected _head: SinglyLinkedListNode<E> | undefined;
|
|
75
122
|
|
|
76
|
-
/**
|
|
77
|
-
* The `head` function returns the first node of a singly linked list.
|
|
78
|
-
* @returns The method is returning either a SinglyLinkedListNode object or undefined.
|
|
79
|
-
*/
|
|
80
123
|
get head(): SinglyLinkedListNode<E> | undefined {
|
|
81
124
|
return this._head;
|
|
82
125
|
}
|
|
83
126
|
|
|
84
127
|
protected _tail: SinglyLinkedListNode<E> | undefined;
|
|
85
128
|
|
|
86
|
-
/**
|
|
87
|
-
* The `tail` function returns the last node of a singly linked list.
|
|
88
|
-
* @returns The method is returning either a SinglyLinkedListNode object or undefined.
|
|
89
|
-
*/
|
|
90
129
|
get tail(): SinglyLinkedListNode<E> | undefined {
|
|
91
130
|
return this._tail;
|
|
92
131
|
}
|
|
93
132
|
|
|
94
|
-
/**
|
|
95
|
-
* The above function returns the value of the first element in a linked list, or undefined if the
|
|
96
|
-
* list is empty.
|
|
97
|
-
* @returns The value of the first node in the linked list, or undefined if the linked list is empty.
|
|
98
|
-
*/
|
|
99
133
|
get first(): E | undefined {
|
|
100
134
|
return this.head?.value;
|
|
101
135
|
}
|
|
102
136
|
|
|
103
|
-
/**
|
|
104
|
-
* The function returns the value of the last element in a linked list, or undefined if the list is
|
|
105
|
-
* empty.
|
|
106
|
-
* @returns The value of the last node in the linked list, or undefined if the linked list is empty.
|
|
107
|
-
*/
|
|
108
137
|
get last(): E | undefined {
|
|
109
138
|
return this.tail?.value;
|
|
110
139
|
}
|
|
111
140
|
|
|
112
|
-
protected
|
|
141
|
+
protected _length: number = 0;
|
|
113
142
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
* @returns The size of the object, which is a number.
|
|
117
|
-
*/
|
|
118
|
-
get size(): number {
|
|
119
|
-
return this._size;
|
|
143
|
+
get length(): number {
|
|
144
|
+
return this._length;
|
|
120
145
|
}
|
|
121
146
|
|
|
122
147
|
/**
|
|
@@ -154,7 +179,8 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
154
179
|
this.tail!.next = newNode;
|
|
155
180
|
this._tail = newNode;
|
|
156
181
|
}
|
|
157
|
-
this.
|
|
182
|
+
this._length++;
|
|
183
|
+
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
158
184
|
return true;
|
|
159
185
|
}
|
|
160
186
|
|
|
@@ -172,7 +198,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
172
198
|
const value = this.head.value;
|
|
173
199
|
this._head = undefined;
|
|
174
200
|
this._tail = undefined;
|
|
175
|
-
this.
|
|
201
|
+
this._length--;
|
|
176
202
|
return value;
|
|
177
203
|
}
|
|
178
204
|
|
|
@@ -183,7 +209,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
183
209
|
const value = this.tail!.value;
|
|
184
210
|
current.next = undefined;
|
|
185
211
|
this._tail = current;
|
|
186
|
-
this.
|
|
212
|
+
this._length--;
|
|
187
213
|
return value;
|
|
188
214
|
}
|
|
189
215
|
|
|
@@ -198,7 +224,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
198
224
|
if (!this.head) return undefined;
|
|
199
225
|
const removedNode = this.head;
|
|
200
226
|
this._head = this.head.next;
|
|
201
|
-
this.
|
|
227
|
+
this._length--;
|
|
202
228
|
return removedNode.value;
|
|
203
229
|
}
|
|
204
230
|
|
|
@@ -222,7 +248,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
222
248
|
newNode.next = this.head;
|
|
223
249
|
this._head = newNode;
|
|
224
250
|
}
|
|
225
|
-
this.
|
|
251
|
+
this._length++;
|
|
226
252
|
return true;
|
|
227
253
|
}
|
|
228
254
|
|
|
@@ -310,7 +336,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
310
336
|
* `undefined` if the index is out of bounds.
|
|
311
337
|
*/
|
|
312
338
|
at(index: number): E | undefined {
|
|
313
|
-
if (index < 0 || index >= this.
|
|
339
|
+
if (index < 0 || index >= this._length) return undefined;
|
|
314
340
|
let current = this.head;
|
|
315
341
|
for (let i = 0; i < index; i++) {
|
|
316
342
|
current = current!.next;
|
|
@@ -365,22 +391,27 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
365
391
|
* @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of
|
|
366
392
|
* bounds.
|
|
367
393
|
*/
|
|
368
|
-
deleteAt(index: number):
|
|
369
|
-
if (index < 0 || index >= this.
|
|
394
|
+
deleteAt(index: number): E | undefined {
|
|
395
|
+
if (index < 0 || index >= this._length) return;
|
|
396
|
+
let deleted: E | undefined;
|
|
370
397
|
if (index === 0) {
|
|
398
|
+
deleted = this.first;
|
|
371
399
|
this.shift();
|
|
372
|
-
return
|
|
400
|
+
return deleted;
|
|
373
401
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
402
|
+
|
|
403
|
+
const targetNode = this.getNodeAt(index);
|
|
404
|
+
const prevNode = this._getPrevNode(targetNode!);
|
|
405
|
+
|
|
406
|
+
if (prevNode && targetNode) {
|
|
407
|
+
deleted = targetNode.value;
|
|
408
|
+
prevNode.next = targetNode.next;
|
|
409
|
+
if (targetNode === this.tail) this._tail = prevNode;
|
|
410
|
+
this._length--;
|
|
411
|
+
return deleted;
|
|
377
412
|
}
|
|
378
413
|
|
|
379
|
-
|
|
380
|
-
const removedNode = prevNode!.next;
|
|
381
|
-
prevNode!.next = removedNode!.next;
|
|
382
|
-
this._size--;
|
|
383
|
-
return true;
|
|
414
|
+
return;
|
|
384
415
|
}
|
|
385
416
|
|
|
386
417
|
/**
|
|
@@ -394,37 +425,25 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
394
425
|
* successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.
|
|
395
426
|
*/
|
|
396
427
|
delete(elementOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {
|
|
397
|
-
if (elementOrNode === undefined) return false;
|
|
398
|
-
let value: E;
|
|
399
|
-
if (elementOrNode instanceof SinglyLinkedListNode) {
|
|
400
|
-
value = elementOrNode.value;
|
|
401
|
-
} else {
|
|
402
|
-
value = elementOrNode;
|
|
403
|
-
}
|
|
404
|
-
let current = this.head,
|
|
405
|
-
prev = undefined;
|
|
428
|
+
if (elementOrNode === undefined || !this.head) return false;
|
|
406
429
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
this._size--;
|
|
421
|
-
return true;
|
|
422
|
-
}
|
|
423
|
-
prev = current;
|
|
424
|
-
current = current.next;
|
|
430
|
+
const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
|
|
431
|
+
|
|
432
|
+
if (!node) return false;
|
|
433
|
+
|
|
434
|
+
const prevNode = this._getPrevNode(node);
|
|
435
|
+
|
|
436
|
+
if (!prevNode) {
|
|
437
|
+
// The node is the head
|
|
438
|
+
this._head = node.next;
|
|
439
|
+
if (node === this.tail) this._tail = undefined;
|
|
440
|
+
} else {
|
|
441
|
+
prevNode.next = node.next;
|
|
442
|
+
if (node === this.tail) this._tail = prevNode;
|
|
425
443
|
}
|
|
426
444
|
|
|
427
|
-
|
|
445
|
+
this._length--;
|
|
446
|
+
return true;
|
|
428
447
|
}
|
|
429
448
|
|
|
430
449
|
/**
|
|
@@ -443,13 +462,13 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
443
462
|
* successfully added at the specified index, and `false` if the index is out of bounds.
|
|
444
463
|
*/
|
|
445
464
|
addAt(index: number, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {
|
|
446
|
-
if (index < 0 || index > this.
|
|
465
|
+
if (index < 0 || index > this._length) return false;
|
|
447
466
|
|
|
448
467
|
if (index === 0) {
|
|
449
468
|
this.unshift(newElementOrNode);
|
|
450
469
|
return true;
|
|
451
470
|
}
|
|
452
|
-
if (index === this.
|
|
471
|
+
if (index === this._length) {
|
|
453
472
|
this.push(newElementOrNode);
|
|
454
473
|
return true;
|
|
455
474
|
}
|
|
@@ -458,10 +477,33 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
458
477
|
const prevNode = this.getNodeAt(index - 1);
|
|
459
478
|
newNode.next = prevNode!.next;
|
|
460
479
|
prevNode!.next = newNode;
|
|
461
|
-
this.
|
|
480
|
+
this._length++;
|
|
462
481
|
return true;
|
|
463
482
|
}
|
|
464
483
|
|
|
484
|
+
/**
|
|
485
|
+
* Time Complexity: O(n)
|
|
486
|
+
* Space Complexity: O(1)
|
|
487
|
+
*
|
|
488
|
+
* The function setAt(index, value) updates the value at a specified index in a data structure if the
|
|
489
|
+
* index exists.
|
|
490
|
+
* @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
|
|
491
|
+
* data structure where you want to set a new value.
|
|
492
|
+
* @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
|
|
493
|
+
* want to set at the specified index in the data structure.
|
|
494
|
+
* @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
|
|
495
|
+
* is successfully updated, and `false` if the index is out of bounds (i.e., the node at that index
|
|
496
|
+
* does not exist).
|
|
497
|
+
*/
|
|
498
|
+
setAt(index: number, value: E): boolean {
|
|
499
|
+
const node = this.getNodeAt(index);
|
|
500
|
+
if (node) {
|
|
501
|
+
node.value = value;
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
|
|
465
507
|
/**
|
|
466
508
|
* Time Complexity: O(1)
|
|
467
509
|
* Space Complexity: O(1)
|
|
@@ -471,7 +513,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
471
513
|
* @returns A boolean value indicating whether the length of the object is equal to 0.
|
|
472
514
|
*/
|
|
473
515
|
isEmpty(): boolean {
|
|
474
|
-
return this.
|
|
516
|
+
return this._length === 0;
|
|
475
517
|
}
|
|
476
518
|
|
|
477
519
|
/**
|
|
@@ -483,24 +525,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
483
525
|
clear(): void {
|
|
484
526
|
this._head = undefined;
|
|
485
527
|
this._tail = undefined;
|
|
486
|
-
this.
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* Time Complexity: O(n)
|
|
491
|
-
* Space Complexity: O(n)
|
|
492
|
-
*
|
|
493
|
-
* The `toArray` function converts a linked list into an array.
|
|
494
|
-
* @returns The `toArray()` method is returning an array of type `E[]`.
|
|
495
|
-
*/
|
|
496
|
-
toArray(): E[] {
|
|
497
|
-
const array: E[] = [];
|
|
498
|
-
let current = this.head;
|
|
499
|
-
while (current) {
|
|
500
|
-
array.push(current.value);
|
|
501
|
-
current = current.next;
|
|
502
|
-
}
|
|
503
|
-
return array;
|
|
528
|
+
this._length = 0;
|
|
504
529
|
}
|
|
505
530
|
|
|
506
531
|
/**
|
|
@@ -528,35 +553,6 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
528
553
|
return this;
|
|
529
554
|
}
|
|
530
555
|
|
|
531
|
-
/**
|
|
532
|
-
* Time Complexity: O(n)
|
|
533
|
-
* Space Complexity: O(1)
|
|
534
|
-
*
|
|
535
|
-
* The `indexOf` function in TypeScript searches for a specific element or node in a singly linked
|
|
536
|
-
* list and returns its index if found.
|
|
537
|
-
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
538
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `indexOf` method can be one
|
|
539
|
-
* of the following types:
|
|
540
|
-
* @returns The `indexOf` method returns the index of the first occurrence of the element that
|
|
541
|
-
* matches the provided predicate in the singly linked list. If no matching element is found, it
|
|
542
|
-
* returns -1.
|
|
543
|
-
*/
|
|
544
|
-
indexOf(elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)): number {
|
|
545
|
-
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
546
|
-
let index = 0;
|
|
547
|
-
let current = this.head;
|
|
548
|
-
|
|
549
|
-
while (current) {
|
|
550
|
-
if (predicate(current)) {
|
|
551
|
-
return index;
|
|
552
|
-
}
|
|
553
|
-
index++;
|
|
554
|
-
current = current.next;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
return -1;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
556
|
/**
|
|
561
557
|
* Time Complexity: O(n)
|
|
562
558
|
* Space Complexity: O(1)
|
|
@@ -574,6 +570,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
574
570
|
elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined
|
|
575
571
|
): SinglyLinkedListNode<E> | undefined {
|
|
576
572
|
if (elementNodeOrPredicate === undefined) return;
|
|
573
|
+
if (this.isNode(elementNodeOrPredicate)) return elementNodeOrPredicate;
|
|
577
574
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
578
575
|
let current = this.head;
|
|
579
576
|
|
|
@@ -607,32 +604,22 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
607
604
|
existingElementOrNode: E | SinglyLinkedListNode<E>,
|
|
608
605
|
newElementOrNode: E | SinglyLinkedListNode<E>
|
|
609
606
|
): boolean {
|
|
610
|
-
|
|
607
|
+
const existingNode = this.getNode(existingElementOrNode);
|
|
608
|
+
if (!existingNode) return false;
|
|
611
609
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
existingValue = existingElementOrNode.value;
|
|
615
|
-
} else {
|
|
616
|
-
existingValue = existingElementOrNode;
|
|
617
|
-
}
|
|
618
|
-
if (this.head.value === existingValue) {
|
|
619
|
-
this.unshift(newElementOrNode);
|
|
620
|
-
return true;
|
|
621
|
-
}
|
|
610
|
+
const prevNode = this._getPrevNode(existingNode);
|
|
611
|
+
const newNode = this._ensureNode(newElementOrNode);
|
|
622
612
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
return true;
|
|
631
|
-
}
|
|
632
|
-
current = current.next;
|
|
613
|
+
if (!prevNode) {
|
|
614
|
+
// Add at the head
|
|
615
|
+
this.unshift(newNode);
|
|
616
|
+
} else {
|
|
617
|
+
prevNode.next = newNode;
|
|
618
|
+
newNode.next = existingNode;
|
|
619
|
+
this._length++;
|
|
633
620
|
}
|
|
634
621
|
|
|
635
|
-
return
|
|
622
|
+
return true;
|
|
636
623
|
}
|
|
637
624
|
|
|
638
625
|
/**
|
|
@@ -661,13 +648,82 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
661
648
|
if (existingNode === this.tail) {
|
|
662
649
|
this._tail = newNode;
|
|
663
650
|
}
|
|
664
|
-
this.
|
|
651
|
+
this._length++;
|
|
665
652
|
return true;
|
|
666
653
|
}
|
|
667
654
|
|
|
668
655
|
return false;
|
|
669
656
|
}
|
|
670
657
|
|
|
658
|
+
/**
|
|
659
|
+
* Time Complexity: O(n)
|
|
660
|
+
* Space Complexity: O(1)
|
|
661
|
+
*
|
|
662
|
+
* The function `splice` in TypeScript overrides the default behavior to remove and insert elements
|
|
663
|
+
* in a singly linked list while handling boundary cases.
|
|
664
|
+
* @param {number} start - The `start` parameter in the `splice` method indicates the index at which
|
|
665
|
+
* to start modifying the list. It specifies the position where elements will be added or removed.
|
|
666
|
+
* @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the
|
|
667
|
+
* number of elements to remove from the array starting at the specified `start` index. If
|
|
668
|
+
* `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new
|
|
669
|
+
* elements can still be inserted at
|
|
670
|
+
* @param {E[]} items - The `items` parameter in the `splice` method represents the elements to be
|
|
671
|
+
* inserted into the list at the specified `start` index. These elements will be inserted in place of
|
|
672
|
+
* the elements that are removed from the list. The `splice` method allows you to add new elements to
|
|
673
|
+
* the list while
|
|
674
|
+
* @returns The `splice` method is returning a `SinglyLinkedList` containing the elements that were
|
|
675
|
+
* removed from the original list during the splice operation.
|
|
676
|
+
*/
|
|
677
|
+
override splice(start: number, deleteCount: number = 0, ...items: E[]): this {
|
|
678
|
+
const removedList = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
679
|
+
|
|
680
|
+
// If `start` is out of range, perform boundary processing
|
|
681
|
+
start = Math.max(0, Math.min(start, this.length));
|
|
682
|
+
deleteCount = Math.max(0, deleteCount);
|
|
683
|
+
|
|
684
|
+
// Find the predecessor node of `start`
|
|
685
|
+
const prevNode = start === 0 ? undefined : this.getNodeAt(start - 1);
|
|
686
|
+
const startNode = prevNode ? prevNode.next : this.head;
|
|
687
|
+
|
|
688
|
+
let current = startNode;
|
|
689
|
+
for (let i = 0; i < deleteCount && current; i++) {
|
|
690
|
+
removedList.push(current.value);
|
|
691
|
+
current = current.next;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const nextNode = current;
|
|
695
|
+
let lastInsertedNode: SinglyLinkedListNode<E> | undefined = undefined;
|
|
696
|
+
|
|
697
|
+
for (const item of items) {
|
|
698
|
+
const newNode = this._ensureNode(item);
|
|
699
|
+
if (!lastInsertedNode) {
|
|
700
|
+
if (prevNode) {
|
|
701
|
+
prevNode.next = newNode;
|
|
702
|
+
} else {
|
|
703
|
+
this._head = newNode;
|
|
704
|
+
}
|
|
705
|
+
} else {
|
|
706
|
+
lastInsertedNode.next = newNode;
|
|
707
|
+
}
|
|
708
|
+
lastInsertedNode = newNode;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Connect new node to `nextNode`
|
|
712
|
+
if (lastInsertedNode) {
|
|
713
|
+
lastInsertedNode.next = nextNode;
|
|
714
|
+
} else if (prevNode) {
|
|
715
|
+
prevNode.next = nextNode;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Update tail node and length
|
|
719
|
+
if (!nextNode) {
|
|
720
|
+
this._tail = lastInsertedNode || prevNode;
|
|
721
|
+
}
|
|
722
|
+
this._length += items.length - removedList.length;
|
|
723
|
+
|
|
724
|
+
return removedList as this;
|
|
725
|
+
}
|
|
726
|
+
|
|
671
727
|
/**
|
|
672
728
|
* Time Complexity: O(n)
|
|
673
729
|
* Space Complexity: O(1)
|
|
@@ -703,8 +759,8 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
703
759
|
* @returns The `clone()` method is returning a new instance of the `SinglyLinkedList` class, which
|
|
704
760
|
* is a clone of the original list.
|
|
705
761
|
*/
|
|
706
|
-
clone():
|
|
707
|
-
return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn });
|
|
762
|
+
clone(): this {
|
|
763
|
+
return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;
|
|
708
764
|
}
|
|
709
765
|
|
|
710
766
|
/**
|
|
@@ -724,8 +780,8 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
724
780
|
* @returns The `filter` method is returning a new `SinglyLinkedList` object that contains the
|
|
725
781
|
* elements that pass the filter condition specified by the `callback` function.
|
|
726
782
|
*/
|
|
727
|
-
filter(callback: ElementCallback<E, R, boolean
|
|
728
|
-
const filteredList =
|
|
783
|
+
filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): SinglyLinkedList<E, R> {
|
|
784
|
+
const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
729
785
|
let index = 0;
|
|
730
786
|
for (const current of this) {
|
|
731
787
|
if (callback.call(thisArg, current, index, this)) {
|
|
@@ -757,11 +813,11 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
757
813
|
* @returns a new instance of the `SinglyLinkedList` class with the mapped elements.
|
|
758
814
|
*/
|
|
759
815
|
map<EM, RM>(
|
|
760
|
-
callback: ElementCallback<E, R, EM
|
|
816
|
+
callback: ElementCallback<E, R, EM>,
|
|
761
817
|
toElementFn?: (rawElement: RM) => EM,
|
|
762
818
|
thisArg?: any
|
|
763
819
|
): SinglyLinkedList<EM, RM> {
|
|
764
|
-
const mappedList = new SinglyLinkedList<EM, RM>([], { toElementFn });
|
|
820
|
+
const mappedList = new SinglyLinkedList<EM, RM>([], { toElementFn, maxLen: this._maxLen });
|
|
765
821
|
let index = 0;
|
|
766
822
|
for (const current of this) {
|
|
767
823
|
mappedList.push(callback.call(thisArg, current, index, this));
|
|
@@ -771,6 +827,20 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
771
827
|
return mappedList;
|
|
772
828
|
}
|
|
773
829
|
|
|
830
|
+
/**
|
|
831
|
+
* The function `_createInstance` returns a new instance of `SinglyLinkedList` with the specified
|
|
832
|
+
* options.
|
|
833
|
+
* @param [options] - The `options` parameter in the `_createInstance` method is of type
|
|
834
|
+
* `SinglyLinkedListOptions<E, R>`, which is used to configure the behavior of the `SinglyLinkedList`
|
|
835
|
+
* instance being created. It is an optional parameter, meaning it can be omitted when calling the
|
|
836
|
+
* method.
|
|
837
|
+
* @returns An instance of the `SinglyLinkedList` class with an empty array and the provided options
|
|
838
|
+
* is being returned.
|
|
839
|
+
*/
|
|
840
|
+
protected override _createInstance(options?: SinglyLinkedListOptions<E, R>): this {
|
|
841
|
+
return new SinglyLinkedList<E, R>([], options) as this;
|
|
842
|
+
}
|
|
843
|
+
|
|
774
844
|
/**
|
|
775
845
|
* The function `_getIterator` returns an iterable iterator that yields the values of a linked list.
|
|
776
846
|
*/
|
|
@@ -783,6 +853,38 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
783
853
|
}
|
|
784
854
|
}
|
|
785
855
|
|
|
856
|
+
/**
|
|
857
|
+
* The function returns an iterator that iterates over the elements of a collection in reverse order.
|
|
858
|
+
*/
|
|
859
|
+
protected *_getReverseIterator(): IterableIterator<E> {
|
|
860
|
+
const reversedArr = [...this].reverse();
|
|
861
|
+
|
|
862
|
+
for (const item of reversedArr) {
|
|
863
|
+
yield item;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* The function `_getNodeIterator` returns an iterator that iterates over the nodes of a singly
|
|
869
|
+
* linked list.
|
|
870
|
+
*/
|
|
871
|
+
protected *_getNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {
|
|
872
|
+
let current = this.head;
|
|
873
|
+
|
|
874
|
+
while (current) {
|
|
875
|
+
yield current;
|
|
876
|
+
current = current.next;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// protected *_getReverseNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {
|
|
881
|
+
// const reversedArr = [...this._getNodeIterator()].reverse();
|
|
882
|
+
//
|
|
883
|
+
// for (const item of reversedArr) {
|
|
884
|
+
// yield item;
|
|
885
|
+
// }
|
|
886
|
+
// }
|
|
887
|
+
|
|
786
888
|
/**
|
|
787
889
|
* The _isPredicate function in TypeScript checks if the input is a function that takes a
|
|
788
890
|
* SinglyLinkedListNode as an argument and returns a boolean.
|
|
@@ -831,4 +933,24 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
|
|
|
831
933
|
|
|
832
934
|
return (node: SinglyLinkedListNode<E>) => node.value === elementNodeOrPredicate;
|
|
833
935
|
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* The function `_getPrevNode` returns the node before a given node in a singly linked list.
|
|
939
|
+
* @param node - The `node` parameter in the `_getPrevNode` method is a reference to a node in a
|
|
940
|
+
* singly linked list. The method is used to find the node that comes before the given node in the
|
|
941
|
+
* linked list.
|
|
942
|
+
* @returns The `_getPrevNode` method returns either the previous node of the input node in a singly
|
|
943
|
+
* linked list or `undefined` if the input node is the head of the list or if the input node is not
|
|
944
|
+
* found in the list.
|
|
945
|
+
*/
|
|
946
|
+
protected _getPrevNode(node: SinglyLinkedListNode<E>): SinglyLinkedListNode<E> | undefined {
|
|
947
|
+
if (!this.head || this.head === node) return undefined;
|
|
948
|
+
|
|
949
|
+
let current = this.head;
|
|
950
|
+
while (current.next && current.next !== node) {
|
|
951
|
+
current = current.next;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
return current.next === node ? current : undefined;
|
|
955
|
+
}
|
|
834
956
|
}
|