data-structure-typed 0.8.6
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/.idea/data-structure-typed.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +2 -0
- package/dist/data-structures/binary-tree/aa-tree.js +6 -0
- package/dist/data-structures/binary-tree/avl-tree.js +231 -0
- package/dist/data-structures/binary-tree/b-tree.js +6 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +31 -0
- package/dist/data-structures/binary-tree/binary-tree.js +992 -0
- package/dist/data-structures/binary-tree/bst.js +431 -0
- package/dist/data-structures/binary-tree/index.js +20 -0
- package/dist/data-structures/binary-tree/rb-tree.js +6 -0
- package/dist/data-structures/binary-tree/segment-tree.js +151 -0
- package/dist/data-structures/binary-tree/splay-tree.js +6 -0
- package/dist/data-structures/binary-tree/tree-multiset.js +16 -0
- package/dist/data-structures/binary-tree/two-three-tree.js +6 -0
- package/dist/data-structures/graph/abstract-graph.js +648 -0
- package/dist/data-structures/graph/directed-graph.js +268 -0
- package/dist/data-structures/graph/index.js +19 -0
- package/dist/data-structures/graph/undirected-graph.js +142 -0
- package/dist/data-structures/hash/coordinate-map.js +24 -0
- package/dist/data-structures/hash/coordinate-set.js +21 -0
- package/dist/data-structures/hash/hash-table.js +2 -0
- package/dist/data-structures/hash/index.js +17 -0
- package/dist/data-structures/hash/pair.js +2 -0
- package/dist/data-structures/hash/tree-map.js +2 -0
- package/dist/data-structures/hash/tree-set.js +2 -0
- package/dist/data-structures/heap/heap.js +114 -0
- package/dist/data-structures/heap/index.js +19 -0
- package/dist/data-structures/heap/max-heap.js +22 -0
- package/dist/data-structures/heap/min-heap.js +22 -0
- package/dist/data-structures/index.js +25 -0
- package/dist/data-structures/linked-list/doubly-linked-list.js +259 -0
- package/dist/data-structures/linked-list/index.js +18 -0
- package/dist/data-structures/linked-list/singly-linked-list.js +660 -0
- package/dist/data-structures/linked-list/skip-linked-list.js +2 -0
- package/dist/data-structures/matrix/index.js +19 -0
- package/dist/data-structures/matrix/matrix.js +14 -0
- package/dist/data-structures/matrix/matrix2d.js +119 -0
- package/dist/data-structures/matrix/navigator.js +78 -0
- package/dist/data-structures/matrix/vector2d.js +161 -0
- package/dist/data-structures/priority-queue/index.js +19 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/priority-queue.js +174 -0
- package/dist/data-structures/queue/deque.js +132 -0
- package/dist/data-structures/queue/index.js +17 -0
- package/dist/data-structures/queue/queue.js +113 -0
- package/dist/data-structures/stack/index.js +17 -0
- package/dist/data-structures/stack/stack.js +97 -0
- package/dist/data-structures/trampoline.js +52 -0
- package/dist/data-structures/trie/index.js +17 -0
- package/dist/data-structures/trie/trie.js +141 -0
- package/dist/index.js +17 -0
- package/dist/types/data-structures/binary-tree/aa-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +21 -0
- package/dist/types/data-structures/binary-tree/b-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +8 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +140 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +32 -0
- package/dist/types/data-structures/binary-tree/index.d.ts +4 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +33 -0
- package/dist/types/data-structures/binary-tree/splay-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/tree-multiset.d.ts +11 -0
- package/dist/types/data-structures/binary-tree/two-three-tree.d.ts +2 -0
- package/dist/types/data-structures/graph/abstract-graph.d.ts +126 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +51 -0
- package/dist/types/data-structures/graph/index.d.ts +3 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +24 -0
- package/dist/types/data-structures/hash/coordinate-map.d.ts +8 -0
- package/dist/types/data-structures/hash/coordinate-set.d.ts +7 -0
- package/dist/types/data-structures/hash/hash-table.d.ts +1 -0
- package/dist/types/data-structures/hash/index.d.ts +1 -0
- package/dist/types/data-structures/hash/pair.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-map.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-set.d.ts +1 -0
- package/dist/types/data-structures/heap/heap.d.ts +72 -0
- package/dist/types/data-structures/heap/index.d.ts +3 -0
- package/dist/types/data-structures/heap/max-heap.d.ts +14 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +14 -0
- package/dist/types/data-structures/index.d.ts +9 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +59 -0
- package/dist/types/data-structures/linked-list/index.d.ts +2 -0
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +358 -0
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +1 -0
- package/dist/types/data-structures/matrix/index.d.ts +3 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +9 -0
- package/dist/types/data-structures/matrix/matrix2d.d.ts +25 -0
- package/dist/types/data-structures/matrix/navigator.d.ts +31 -0
- package/dist/types/data-structures/matrix/vector2d.d.ts +74 -0
- package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +36 -0
- package/dist/types/data-structures/queue/deque.d.ts +37 -0
- package/dist/types/data-structures/queue/index.d.ts +1 -0
- package/dist/types/data-structures/queue/queue.d.ts +76 -0
- package/dist/types/data-structures/stack/index.d.ts +1 -0
- package/dist/types/data-structures/stack/stack.d.ts +69 -0
- package/dist/types/data-structures/trampoline.d.ts +25 -0
- package/dist/types/data-structures/trie/index.d.ts +1 -0
- package/dist/types/data-structures/trie/trie.d.ts +28 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +17 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/utils.d.ts +46 -0
- package/dist/types/utils.d.ts +122 -0
- package/dist/types/utils.js +53 -0
- package/dist/utils.js +569 -0
- package/package.json +75 -0
- package/src/data-structures/binary-tree/aa-tree.ts +3 -0
- package/src/data-structures/binary-tree/avl-tree.ts +232 -0
- package/src/data-structures/binary-tree/b-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +33 -0
- package/src/data-structures/binary-tree/binary-tree.ts +1088 -0
- package/src/data-structures/binary-tree/bst.ts +404 -0
- package/src/data-structures/binary-tree/index.ts +4 -0
- package/src/data-structures/binary-tree/rb-tree.ts +3 -0
- package/src/data-structures/binary-tree/segment-tree.ts +164 -0
- package/src/data-structures/binary-tree/splay-tree.ts +3 -0
- package/src/data-structures/binary-tree/tree-multiset.ts +21 -0
- package/src/data-structures/binary-tree/two-three-tree.ts +3 -0
- package/src/data-structures/graph/abstract-graph.ts +789 -0
- package/src/data-structures/graph/directed-graph.ts +322 -0
- package/src/data-structures/graph/index.ts +3 -0
- package/src/data-structures/graph/undirected-graph.ts +154 -0
- package/src/data-structures/hash/coordinate-map.ts +24 -0
- package/src/data-structures/hash/coordinate-set.ts +20 -0
- package/src/data-structures/hash/hash-table.ts +1 -0
- package/src/data-structures/hash/index.ts +1 -0
- package/src/data-structures/hash/pair.ts +1 -0
- package/src/data-structures/hash/tree-map.ts +1 -0
- package/src/data-structures/hash/tree-set.ts +1 -0
- package/src/data-structures/heap/heap.ts +136 -0
- package/src/data-structures/heap/index.ts +3 -0
- package/src/data-structures/heap/max-heap.ts +22 -0
- package/src/data-structures/heap/min-heap.ts +24 -0
- package/src/data-structures/index.ts +10 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +258 -0
- package/src/data-structures/linked-list/index.ts +2 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +750 -0
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -0
- package/src/data-structures/matrix/index.ts +3 -0
- package/src/data-structures/matrix/matrix.ts +13 -0
- package/src/data-structures/matrix/matrix2d.ts +125 -0
- package/src/data-structures/matrix/navigator.ts +99 -0
- package/src/data-structures/matrix/vector2d.ts +189 -0
- package/src/data-structures/priority-queue/index.ts +3 -0
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/priority-queue.ts +208 -0
- package/src/data-structures/queue/deque.ts +139 -0
- package/src/data-structures/queue/index.ts +1 -0
- package/src/data-structures/queue/queue.ts +123 -0
- package/src/data-structures/stack/index.ts +1 -0
- package/src/data-structures/stack/stack.ts +104 -0
- package/src/data-structures/trampoline.ts +91 -0
- package/src/data-structures/trie/index.ts +1 -0
- package/src/data-structures/trie/trie.ts +153 -0
- package/src/index.ts +1 -0
- package/src/types/index.ts +1 -0
- package/src/types/patches/index.d.ts +0 -0
- package/src/types/utils.ts +158 -0
- package/src/utils.ts +605 -0
- package/tsconfig.json +52 -0
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SinglyLinkedList = exports.SinglyLinkedListNode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The class which represents one link or node in a linked list
|
|
6
|
+
* ```ts
|
|
7
|
+
* const node = new SinglyLinkedListNode(1, null, null, null);
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
class SinglyLinkedListNode {
|
|
11
|
+
constructor(
|
|
12
|
+
/** Data stored on the node */
|
|
13
|
+
val,
|
|
14
|
+
/** The previous node in the list */
|
|
15
|
+
prev,
|
|
16
|
+
/** The next link in the list */
|
|
17
|
+
next,
|
|
18
|
+
/** The list this node belongs to */
|
|
19
|
+
list) {
|
|
20
|
+
this.val = val;
|
|
21
|
+
this.prev = prev;
|
|
22
|
+
this.next = next;
|
|
23
|
+
this.list = list;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Alias to .val
|
|
27
|
+
* ```ts
|
|
28
|
+
* new LinkedList(1, 2, 3).head.value; // 1
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
get value() {
|
|
32
|
+
return this.val;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get the index of this node
|
|
36
|
+
* ```ts
|
|
37
|
+
* new LinkedList(1, 2, 3).head.index; // 0
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
get index() {
|
|
41
|
+
if (!this.list) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return this.list.findIndex((value) => value === this.value);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Insert a new node before this one
|
|
48
|
+
* ```ts
|
|
49
|
+
* new LinkedList(2, 3).head.insertBefore(1); // 1 <=> 2 <=> 3
|
|
50
|
+
* ```
|
|
51
|
+
* @param val Data to save in the node
|
|
52
|
+
*/
|
|
53
|
+
insertBefore(val) {
|
|
54
|
+
return this.list !== null
|
|
55
|
+
? this.list.insertBefore(this, val)
|
|
56
|
+
: new SinglyLinkedList(val, this.val);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Insert new val after this node
|
|
60
|
+
* ```ts
|
|
61
|
+
* new LinkedList(1, 2).tail.insertAfter(3); // 1 <=> 2 <=> 3
|
|
62
|
+
* ```
|
|
63
|
+
* @param val Data to be saved in the node
|
|
64
|
+
*/
|
|
65
|
+
insertAfter(val) {
|
|
66
|
+
return this.list !== null
|
|
67
|
+
? this.list.insertAfter(this, val)
|
|
68
|
+
: new SinglyLinkedList(this.val, val);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Remove this node
|
|
72
|
+
* ```ts
|
|
73
|
+
* new LinkedList(1, 2, 3, 4).tail.remove(); // 1 <=> 2 <=> 3
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
remove() {
|
|
77
|
+
if (this.list === null) {
|
|
78
|
+
throw new ReferenceError('Node does not belong to any list');
|
|
79
|
+
}
|
|
80
|
+
return this.list.removeNode(this);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.SinglyLinkedListNode = SinglyLinkedListNode;
|
|
84
|
+
/**
|
|
85
|
+
* A doubly linked list
|
|
86
|
+
* ```ts
|
|
87
|
+
* const list = new LinkedList(1, 2, 3);
|
|
88
|
+
* const listFromArray = LinkedList.from([1, 2, 3]);
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
class SinglyLinkedList {
|
|
92
|
+
/**
|
|
93
|
+
* The length of the list
|
|
94
|
+
*/
|
|
95
|
+
get length() {
|
|
96
|
+
return this.size;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Convert any iterable to a new linked list
|
|
100
|
+
* ```javascript
|
|
101
|
+
* const array = [1, 2, 3];
|
|
102
|
+
* const list = LinkedList.from(array);
|
|
103
|
+
* ```
|
|
104
|
+
* @param iterable Any iterable datatype like Array or Map
|
|
105
|
+
*/
|
|
106
|
+
static from(iterable) {
|
|
107
|
+
return new SinglyLinkedList(...iterable);
|
|
108
|
+
}
|
|
109
|
+
constructor(...args) {
|
|
110
|
+
this.head = null;
|
|
111
|
+
this.tail = null;
|
|
112
|
+
this.size = 0;
|
|
113
|
+
for (let i = 0; i < arguments.length; i++) {
|
|
114
|
+
this.append(args[i]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get the node val at a specified index, zero based
|
|
119
|
+
* ```ts
|
|
120
|
+
* new LinkedList(1, 2, 3).get(0); // 1
|
|
121
|
+
* ```
|
|
122
|
+
* @param index to retrieve val at
|
|
123
|
+
*/
|
|
124
|
+
get(index) {
|
|
125
|
+
const node = this.getNode(index);
|
|
126
|
+
return node !== undefined ? node.val : undefined;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get the node at index, zero based
|
|
130
|
+
* ```ts
|
|
131
|
+
* new LinkedList(1, 2, 3).getNode(0);
|
|
132
|
+
* // { prev: null, val: 1, next: SinglyLinkedListNode }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
getNode(index) {
|
|
136
|
+
if (this.head === null || index < 0 || index >= this.length) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
const asc = index < this.length / 2;
|
|
140
|
+
const stopAt = asc ? index : this.length - index - 1;
|
|
141
|
+
const nextNode = asc ? 'next' : 'prev';
|
|
142
|
+
let currentNode = asc ? this.head : this.tail;
|
|
143
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
144
|
+
for (let currentIndex = 0; currentIndex < stopAt; currentIndex++) {
|
|
145
|
+
if (currentNode) {
|
|
146
|
+
currentNode = currentNode[nextNode];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return currentNode || undefined;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Return the first node and its index in the list that
|
|
153
|
+
* satisfies the testing function
|
|
154
|
+
* ```ts
|
|
155
|
+
* new LinkedList(1, 2, 3).findNodeIndex(val => val === 1);
|
|
156
|
+
* // { node: SinglyLinkedListNode, index: 0 }
|
|
157
|
+
* ```
|
|
158
|
+
* @param f A function to be applied to the val of each node
|
|
159
|
+
*/
|
|
160
|
+
findNodeIndex(f) {
|
|
161
|
+
let currentIndex = 0;
|
|
162
|
+
let currentNode = this.head;
|
|
163
|
+
while (currentNode) {
|
|
164
|
+
if (f(currentNode.val, currentIndex, this)) {
|
|
165
|
+
return {
|
|
166
|
+
index: currentIndex,
|
|
167
|
+
node: currentNode,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
currentNode = currentNode.next;
|
|
171
|
+
currentIndex += 1;
|
|
172
|
+
}
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns the first node in the list that
|
|
177
|
+
* satisfies the provided testing function. Otherwise undefined is returned.
|
|
178
|
+
* ```ts
|
|
179
|
+
* new LinkedList(1, 2, 3).findNode(val => val === 1);
|
|
180
|
+
* // { prev: null, val: 1, next: SinglyLinkedListNode }
|
|
181
|
+
* ```
|
|
182
|
+
* @param f Function to test val against
|
|
183
|
+
*/
|
|
184
|
+
findNode(f) {
|
|
185
|
+
const nodeIndex = this.findNodeIndex(f);
|
|
186
|
+
return nodeIndex !== undefined ? nodeIndex.node : undefined;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Returns the value of the first element in the list that
|
|
190
|
+
* satisfies the provided testing function. Otherwise undefined is returned.
|
|
191
|
+
* ```ts
|
|
192
|
+
* new LinkedList(1, 2, 3).find(val => val === 1); // 1
|
|
193
|
+
* ```
|
|
194
|
+
* @param f Function to test val against
|
|
195
|
+
*/
|
|
196
|
+
find(f) {
|
|
197
|
+
const nodeIndex = this.findNodeIndex(f);
|
|
198
|
+
return nodeIndex !== undefined ? nodeIndex.node.val : undefined;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Returns the index of the first node in the list that
|
|
202
|
+
* satisfies the provided testing function. Ohterwise -1 is returned.
|
|
203
|
+
* ```ts
|
|
204
|
+
* new LinkedList(1, 2, 3).findIndex(val => val === 3); // 2
|
|
205
|
+
* ```
|
|
206
|
+
* @param f Function to test val against
|
|
207
|
+
*/
|
|
208
|
+
findIndex(f) {
|
|
209
|
+
const nodeIndex = this.findNodeIndex(f);
|
|
210
|
+
return nodeIndex !== undefined ? nodeIndex.index : -1;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Append one or any number of nodes to the end of the list.
|
|
214
|
+
* This modifies the list in place and returns the list itself
|
|
215
|
+
* to make this method chainable.
|
|
216
|
+
* ```ts
|
|
217
|
+
* new LinkedList(1).append(2).append(3, 4); // 1 <=> 2 <=> 3 <=> 4
|
|
218
|
+
* ```
|
|
219
|
+
* @param args Data to be stored in the node, takes any number of arguments
|
|
220
|
+
*/
|
|
221
|
+
append(...args) {
|
|
222
|
+
for (const val of args) {
|
|
223
|
+
const node = new SinglyLinkedListNode(val, this.tail, null, this);
|
|
224
|
+
if (this.head === null) {
|
|
225
|
+
this.head = node;
|
|
226
|
+
}
|
|
227
|
+
if (this.tail !== null) {
|
|
228
|
+
this.tail.next = node;
|
|
229
|
+
}
|
|
230
|
+
this.tail = node;
|
|
231
|
+
this.size += 1;
|
|
232
|
+
}
|
|
233
|
+
return this;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Synonym for append
|
|
237
|
+
* ```ts
|
|
238
|
+
* new LinkedList(1).push(2).push(3, 4); // 1 <=> 2 <=> 3 <=> 4
|
|
239
|
+
* ```
|
|
240
|
+
* @param args Data to be stored, takes any number of arguments
|
|
241
|
+
*/
|
|
242
|
+
push(...args) {
|
|
243
|
+
this.append(...args);
|
|
244
|
+
return this.length;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Prepend any number of val arguments to the list. The
|
|
248
|
+
* argument list is prepended as a block to reduce confusion:
|
|
249
|
+
* ```javascript
|
|
250
|
+
* new LinkedList(3, 4).prepend(0, 1, 2); // [0, 1, 2, 3, 4]
|
|
251
|
+
* ```
|
|
252
|
+
* @param args Data to be stored in the node, accepts any number of arguments
|
|
253
|
+
*/
|
|
254
|
+
prepend(...args) {
|
|
255
|
+
const reverseArgs = Array.from(args).reverse();
|
|
256
|
+
for (const val of reverseArgs) {
|
|
257
|
+
const node = new SinglyLinkedListNode(val, null, this.head, this);
|
|
258
|
+
if (this.tail === null) {
|
|
259
|
+
this.tail = node;
|
|
260
|
+
}
|
|
261
|
+
if (this.head !== null) {
|
|
262
|
+
this.head.prev = node;
|
|
263
|
+
}
|
|
264
|
+
this.head = node;
|
|
265
|
+
this.size += 1;
|
|
266
|
+
}
|
|
267
|
+
return this;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Insert a new node at a given index position. If index is
|
|
271
|
+
* out of bounds, the node is appended, if index is negative
|
|
272
|
+
* or 0, it will be prepended.
|
|
273
|
+
* ```ts
|
|
274
|
+
* new LinkedList(1, 3).insertAt(1, 2); // 1 <=> 2 <=> 3
|
|
275
|
+
* ```
|
|
276
|
+
* @param index The index to insert the new node at
|
|
277
|
+
* @param val Data to be stored on the new node
|
|
278
|
+
*/
|
|
279
|
+
insertAt(index, val) {
|
|
280
|
+
if (this.head === null) {
|
|
281
|
+
return this.append(val);
|
|
282
|
+
}
|
|
283
|
+
if (index <= 0) {
|
|
284
|
+
return this.prepend(val);
|
|
285
|
+
}
|
|
286
|
+
let currentNode = this.head;
|
|
287
|
+
let currentIndex = 0;
|
|
288
|
+
while (currentIndex < index - 1 && currentNode.next !== null) {
|
|
289
|
+
currentIndex += 1;
|
|
290
|
+
currentNode = currentNode.next;
|
|
291
|
+
}
|
|
292
|
+
currentNode.insertAfter(val);
|
|
293
|
+
return this;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Remove the specified node from the list and return the removed
|
|
297
|
+
* node afterwards.
|
|
298
|
+
* ```ts
|
|
299
|
+
* const list = new LinkedList(1, 2, 3);
|
|
300
|
+
* list.removeNode(list.tail); // { prev: null, val: 3, next: null, list: null }
|
|
301
|
+
* ```
|
|
302
|
+
* @param node The node to be removed
|
|
303
|
+
*/
|
|
304
|
+
removeNode(node) {
|
|
305
|
+
if (node.list !== this) {
|
|
306
|
+
throw new ReferenceError('Node does not belong to this list');
|
|
307
|
+
}
|
|
308
|
+
if (node.prev !== null) {
|
|
309
|
+
node.prev.next = node.next;
|
|
310
|
+
}
|
|
311
|
+
if (node.next !== null) {
|
|
312
|
+
node.next.prev = node.prev;
|
|
313
|
+
}
|
|
314
|
+
if (this.head === node) {
|
|
315
|
+
this.head = node.next;
|
|
316
|
+
}
|
|
317
|
+
if (this.tail === node) {
|
|
318
|
+
this.tail = node.prev;
|
|
319
|
+
}
|
|
320
|
+
this.size -= 1;
|
|
321
|
+
node.next = null;
|
|
322
|
+
node.prev = null;
|
|
323
|
+
node.list = null;
|
|
324
|
+
return node;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Remove the node at the specified index
|
|
328
|
+
* ```ts
|
|
329
|
+
* new LinkedList(1, 2, 3).removeAt(2); // { prev: null, val: 3, next: null, list: null }
|
|
330
|
+
* ```
|
|
331
|
+
* @param index Index at which to remove
|
|
332
|
+
*/
|
|
333
|
+
removeAt(index) {
|
|
334
|
+
const node = this.getNode(index);
|
|
335
|
+
return node !== undefined ? this.removeNode(node) : undefined;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Insert a new node before the reference node
|
|
339
|
+
* ```ts
|
|
340
|
+
* const list = new LinkedList(1, 3);
|
|
341
|
+
* list.insertBefore(list.tail, 2); // 1 <=> 2 <=> 3
|
|
342
|
+
* ```
|
|
343
|
+
* @param referenceNode The node reference
|
|
344
|
+
* @param val Data to save in the node
|
|
345
|
+
*/
|
|
346
|
+
insertBefore(referenceNode, val) {
|
|
347
|
+
const node = new SinglyLinkedListNode(val, referenceNode.prev, referenceNode, this);
|
|
348
|
+
if (referenceNode.prev === null) {
|
|
349
|
+
this.head = node;
|
|
350
|
+
}
|
|
351
|
+
if (referenceNode.prev !== null) {
|
|
352
|
+
referenceNode.prev.next = node;
|
|
353
|
+
}
|
|
354
|
+
referenceNode.prev = node;
|
|
355
|
+
this.size += 1;
|
|
356
|
+
return this;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Sorts the linked list using the provided compare function
|
|
360
|
+
* @param compare A function used to compare the val of two nodes. It should return
|
|
361
|
+
* a boolean. True will insert a before b, false will insert b before a.
|
|
362
|
+
* (a, b) => a < b or (1, 2) => 1 < 2 === true, 2 will be inserted after 1,
|
|
363
|
+
* the sort order will be ascending.
|
|
364
|
+
*/
|
|
365
|
+
sort(compare) {
|
|
366
|
+
if (this.head === null || this.tail === null) {
|
|
367
|
+
return this;
|
|
368
|
+
}
|
|
369
|
+
if (this.length < 2) {
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
372
|
+
const quicksort = (start, end) => {
|
|
373
|
+
if (start === end) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const pivotData = end.val;
|
|
377
|
+
let current = start;
|
|
378
|
+
let split = start;
|
|
379
|
+
while (current && current !== end) {
|
|
380
|
+
const sort = compare(current.val, pivotData);
|
|
381
|
+
if (sort) {
|
|
382
|
+
if (current !== split) {
|
|
383
|
+
const temp = split.val;
|
|
384
|
+
split.val = current.val;
|
|
385
|
+
current.val = temp;
|
|
386
|
+
}
|
|
387
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
388
|
+
if (split.next) {
|
|
389
|
+
split = split.next;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
current = current.next;
|
|
393
|
+
}
|
|
394
|
+
end.val = split.val;
|
|
395
|
+
split.val = pivotData;
|
|
396
|
+
if (start.next === end.prev) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (split.prev && split !== start) {
|
|
400
|
+
quicksort(start, split.prev);
|
|
401
|
+
}
|
|
402
|
+
if (split.next && split !== end) {
|
|
403
|
+
quicksort(split.next, end);
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
quicksort(this.head, this.tail);
|
|
407
|
+
return this;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Insert a new node after this one
|
|
411
|
+
* ```ts
|
|
412
|
+
* const list = new LinkedList(2, 3);
|
|
413
|
+
* list.insertAfter(list.head, 1); // 1 <=> 2 <=> 3
|
|
414
|
+
* ```
|
|
415
|
+
* @param referenceNode The reference node
|
|
416
|
+
* @param val Data to be saved in the node
|
|
417
|
+
*/
|
|
418
|
+
insertAfter(referenceNode, val) {
|
|
419
|
+
const node = new SinglyLinkedListNode(val, referenceNode, referenceNode.next, this);
|
|
420
|
+
if (referenceNode.next === null) {
|
|
421
|
+
this.tail = node;
|
|
422
|
+
}
|
|
423
|
+
if (referenceNode.next !== null) {
|
|
424
|
+
referenceNode.next.prev = node;
|
|
425
|
+
}
|
|
426
|
+
referenceNode.next = node;
|
|
427
|
+
this.size += 1;
|
|
428
|
+
return this;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Remove the first node from the list and return the val of the removed node
|
|
432
|
+
* or undefined
|
|
433
|
+
* ```ts
|
|
434
|
+
* new LinkedList(1, 2, 3).shift(); // 1
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
shift() {
|
|
438
|
+
return this.removeFromAnyEnd(this.head);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Remove the last node from the list and return the val of the removed node
|
|
442
|
+
* or undefined if the list was empty
|
|
443
|
+
* ```ts
|
|
444
|
+
* new LinkedList(1, 2, 3).pop(); // 3
|
|
445
|
+
* ```
|
|
446
|
+
*/
|
|
447
|
+
pop() {
|
|
448
|
+
return this.removeFromAnyEnd(this.tail);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Merge the current list with another. Both lists will be
|
|
452
|
+
* equal after merging.
|
|
453
|
+
* ```ts
|
|
454
|
+
* const list = new LinkedList(1, 2);
|
|
455
|
+
* const otherList = new LinkedList(3);
|
|
456
|
+
* list.merge(otherList);
|
|
457
|
+
* (list === otherList); // true
|
|
458
|
+
* ```
|
|
459
|
+
* @param list The list to be merged
|
|
460
|
+
*/
|
|
461
|
+
merge(list) {
|
|
462
|
+
if (this.tail !== null) {
|
|
463
|
+
this.tail.next = list.head;
|
|
464
|
+
}
|
|
465
|
+
if (list.head !== null) {
|
|
466
|
+
list.head.prev = this.tail;
|
|
467
|
+
}
|
|
468
|
+
this.head = this.head || list.head;
|
|
469
|
+
this.tail = list.tail || this.tail;
|
|
470
|
+
this.size += list.size;
|
|
471
|
+
list.size = this.size;
|
|
472
|
+
list.head = this.head;
|
|
473
|
+
list.tail = this.tail;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Removes all nodes from a list
|
|
477
|
+
*
|
|
478
|
+
* ```ts
|
|
479
|
+
* list.clear();
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
clear() {
|
|
483
|
+
this.head = null;
|
|
484
|
+
this.tail = null;
|
|
485
|
+
this.size = 0;
|
|
486
|
+
return this;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* The slice() method returns a shallow copy of a
|
|
490
|
+
* portion of a list into a new list object selected
|
|
491
|
+
* from start to end (end not included).
|
|
492
|
+
* The original list will not be modified.
|
|
493
|
+
* ```ts
|
|
494
|
+
* const list = new LinkedList(1, 2, 3, 4, 5);
|
|
495
|
+
* const newList = list.slice(0, 3); // 1 <=> 2 <=> 3
|
|
496
|
+
* ```
|
|
497
|
+
* @param start Start index
|
|
498
|
+
* @param end End index, optional
|
|
499
|
+
*/
|
|
500
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
501
|
+
slice(start, end) {
|
|
502
|
+
const list = new SinglyLinkedList();
|
|
503
|
+
let finish = end;
|
|
504
|
+
if (this.head === null || this.tail === null) {
|
|
505
|
+
return list;
|
|
506
|
+
}
|
|
507
|
+
if (finish === undefined || finish < start) {
|
|
508
|
+
finish = this.length;
|
|
509
|
+
}
|
|
510
|
+
let head = this.getNode(start);
|
|
511
|
+
for (let i = 0; i < finish - start && head !== null && head !== undefined; i++) {
|
|
512
|
+
list.append(head.val);
|
|
513
|
+
head = head.next;
|
|
514
|
+
}
|
|
515
|
+
return list;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* The reverse() function reverses the list in place and returns the list
|
|
519
|
+
* itself.
|
|
520
|
+
* ```ts
|
|
521
|
+
* new LinkedList(1, 2, 3).reverse(); // 3 <=> 2 <=> 1
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
reverse() {
|
|
525
|
+
let currentNode = this.head;
|
|
526
|
+
while (currentNode) {
|
|
527
|
+
const next = currentNode.next;
|
|
528
|
+
currentNode.next = currentNode.prev;
|
|
529
|
+
currentNode.prev = next;
|
|
530
|
+
currentNode = currentNode.prev;
|
|
531
|
+
}
|
|
532
|
+
const tail = this.tail;
|
|
533
|
+
this.tail = this.head;
|
|
534
|
+
this.head = tail;
|
|
535
|
+
return this;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* The forEach() method executes a provided function once for each list node.
|
|
539
|
+
* ```ts
|
|
540
|
+
* new LinkedList(1, 2, 3).forEach(val => log(val)); // 1 2 3
|
|
541
|
+
* ```
|
|
542
|
+
* @param f Function to execute for each element, taking up to three arguments.
|
|
543
|
+
* @param reverse Indicates if the list should be walked in reverse order, default is false
|
|
544
|
+
*/
|
|
545
|
+
forEach(f, reverse = false) {
|
|
546
|
+
let currentIndex = reverse ? this.length - 1 : 0;
|
|
547
|
+
let currentNode = reverse ? this.tail : this.head;
|
|
548
|
+
const modifier = reverse ? -1 : 1;
|
|
549
|
+
const nextNode = reverse ? 'prev' : 'next';
|
|
550
|
+
while (currentNode) {
|
|
551
|
+
f(currentNode.val, currentIndex, this);
|
|
552
|
+
currentNode = currentNode[nextNode];
|
|
553
|
+
currentIndex += modifier;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* The map() method creates a new list with the results of
|
|
558
|
+
* calling a provided function on every node in the calling list.
|
|
559
|
+
* ```ts
|
|
560
|
+
* new LinkedList(1, 2, 3).map(val => val + 10); // 11 <=> 12 <=> 13
|
|
561
|
+
* ```
|
|
562
|
+
* @param f Function that produces an node of the new list, taking up to three arguments
|
|
563
|
+
* @param reverse Indicates if the list should be mapped in reverse order, default is false
|
|
564
|
+
*/
|
|
565
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
566
|
+
map(f, reverse = false) {
|
|
567
|
+
const list = new SinglyLinkedList();
|
|
568
|
+
this.forEach((val, index) => list.append(f(val, index, this)), reverse);
|
|
569
|
+
return list;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* The filter() method creates a new list with all nodes
|
|
573
|
+
* that pass the test implemented by the provided function.
|
|
574
|
+
* ```ts
|
|
575
|
+
* new LinkedList(1, 2, 3, 4, 5).filter(val => val < 4); // 1 <=> 2 <=> 3
|
|
576
|
+
* ```
|
|
577
|
+
* @param f Function to test each node val in the list. Return true to keep the node
|
|
578
|
+
* @param reverse Indicates if the list should be filtered in reverse order, default is false
|
|
579
|
+
*/
|
|
580
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
581
|
+
filter(f, reverse = false) {
|
|
582
|
+
const list = new SinglyLinkedList();
|
|
583
|
+
this.forEach((val, index) => {
|
|
584
|
+
if (f(val, index, this)) {
|
|
585
|
+
list.append(val);
|
|
586
|
+
}
|
|
587
|
+
}, reverse);
|
|
588
|
+
return list;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Reduce over each node in the list
|
|
592
|
+
* ```ts
|
|
593
|
+
* new LinkedList(1, 2, 3).reduce(n => n += 1, 0); // 3
|
|
594
|
+
* ```
|
|
595
|
+
* @param f A reducer function
|
|
596
|
+
* @param start An initial value
|
|
597
|
+
* @returns The final state of the accumulator
|
|
598
|
+
*/
|
|
599
|
+
reduce(f, start, reverse = false) {
|
|
600
|
+
let currentIndex = reverse ? this.length - 1 : 0;
|
|
601
|
+
const modifier = reverse ? -1 : 1;
|
|
602
|
+
const nextNode = reverse ? 'prev' : 'next';
|
|
603
|
+
let currentElement = reverse ? this.tail : this.head;
|
|
604
|
+
let result;
|
|
605
|
+
if (start !== undefined) {
|
|
606
|
+
result = start;
|
|
607
|
+
}
|
|
608
|
+
else if (currentElement) {
|
|
609
|
+
result = currentElement.val;
|
|
610
|
+
currentElement = currentElement[nextNode];
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
throw new TypeError('Reduce of empty LinkedList with no initial value');
|
|
614
|
+
}
|
|
615
|
+
while (currentElement) {
|
|
616
|
+
result = f(result, currentElement.val, currentIndex, this);
|
|
617
|
+
currentIndex += modifier;
|
|
618
|
+
currentElement = currentElement[nextNode];
|
|
619
|
+
}
|
|
620
|
+
return result;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Convert the linked list to an array
|
|
624
|
+
* ```ts
|
|
625
|
+
* new LinkedList(1, 2, 3).toArray(); // [1, 2, 3]
|
|
626
|
+
* ```
|
|
627
|
+
*/
|
|
628
|
+
toArray() {
|
|
629
|
+
return [...this];
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Convert a linked list to string
|
|
633
|
+
* ```ts
|
|
634
|
+
* new LinkedList('one', 'two', 'three').toString(' <=> ') === 'one <=> two <=> three';
|
|
635
|
+
* ```
|
|
636
|
+
* @param separator Optional string to be placed in between val nodes, default is one space
|
|
637
|
+
*/
|
|
638
|
+
toString(separator = ' ') {
|
|
639
|
+
return this.reduce((s, val) => `${s}${separator}${val}`);
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* The iterator implementation
|
|
643
|
+
* ```ts
|
|
644
|
+
* const list = new LinkedList(1, 2, 3);
|
|
645
|
+
* for (const val of list) { log(val); } // 1 2 3
|
|
646
|
+
* ```
|
|
647
|
+
*/
|
|
648
|
+
*[Symbol.iterator]() {
|
|
649
|
+
let element = this.head;
|
|
650
|
+
while (element !== null) {
|
|
651
|
+
yield element.val;
|
|
652
|
+
element = element.next;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
/** Private helper function to reduce duplication of pop() and shift() methods */
|
|
656
|
+
removeFromAnyEnd(node) {
|
|
657
|
+
return node !== null ? this.removeNode(node).val : undefined;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
exports.SinglyLinkedList = SinglyLinkedList;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./matrix"), exports);
|
|
18
|
+
__exportStar(require("./vector2d"), exports);
|
|
19
|
+
__exportStar(require("./matrix2d"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MatrixNTI2D = void 0;
|
|
4
|
+
// todo need to be improved
|
|
5
|
+
class MatrixNTI2D {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
const { row, col, initialVal } = options;
|
|
8
|
+
this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0));
|
|
9
|
+
}
|
|
10
|
+
toArray() {
|
|
11
|
+
return this._matrix;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.MatrixNTI2D = MatrixNTI2D;
|