Skip to content

Commit 5a3b443

Browse files
authored
Merge pull request #22 from datastructures-js/enhancements
Enhancements
2 parents efed976 + b31bfe0 commit 5a3b443

11 files changed

+230
-19
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"rules": {
3-
"max-len": ["error", { "code": 80, "ignoreComments": true }],
3+
"max-len": ["error", { "code": 120, "ignoreComments": true }],
44
"comma-dangle": ["error", {
55
"functions": "ignore"
66
}],

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
## [5.2.0] - 2022-02-14
9+
### Added
10+
- `.find` now accepts a second param as the starting node in both types.
11+
- `.findReverse` added to DoublyLinkedList.
12+
- `.fromArray` static method added to both types.
13+
814
## [5.1.1] - 2021-06-20
915
### Fixed
1016
- index.d.ts

DoublyLinkedList.md

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* [.insertAt(position, value)](#insertatposition-value)
1414
* [.forEach(cb)](#foreachcb)
1515
* [.forEachReverse(cb)](#foreachreversecb)
16-
* [.find(cb)](#findcb)
16+
* [.find(cb[, startingNode])](#findcb-startingnode)
17+
* [.findReverse(cb[, startingNode])](#findreversecb-startingnode)
1718
* [.filter(cb)](#filtercb)
1819
* [.toArray()](#toarray)
1920
* [.isEmpty()](#isempty)
@@ -26,6 +27,7 @@
2627
* [.removeAt(position)](#removeatposition)
2728
* [.removeEach(cb)](#removeeachcb)
2829
* [.clear()](#clear)
30+
* [DoublyLinkedList.fromArray(values)](#doublylinkedlistfromarrayvalues)
2931
* [DoublyLinkedListNode](#doublylinkedlistnode)
3032
* [Build](#build)
3133
* [License](#license)
@@ -198,8 +200,8 @@ doublyLinkedList.forEachReverse(
198200
*/
199201
```
200202

201-
### .find(cb)
202-
Finds the first node that returns true from the callback or null if nothing found.
203+
### .find(cb[, startingNode])
204+
Finds the first node that returns true from the callback or null if nothing found. It accepts a second param as the starting node to search.
203205

204206
<table>
205207
<tr>
@@ -208,8 +210,39 @@ Finds the first node that returns true from the callback or null if nothing foun
208210
<th align="center">runtime</th>
209211
</tr>
210212
<tr>
213+
<td>
214+
cb: (node: DoublyLinkedListNode&lt;T&gt;) => boolean
215+
<br />
216+
<i>startingNode: DoublyLinkedListNode&lt;T&gt;</i>
217+
</td>
211218
<td align="center">
219+
<a href="#doublylinkedlistnodet">DoublyLinkedListNode&lt;T&gt;</a>
220+
</td>
221+
<td align="center">O(n)</td>
222+
</tr>
223+
</table>
224+
225+
```js
226+
const node5 = doublyLinkedList.find(
227+
(node, position) => node.getValue() === 5
228+
);
229+
console.log(node5.getValue()); // 5
230+
```
231+
232+
### .findReverse(cb[, startingNode])
233+
Reversevly finds the first node that returns true from the callback or null if nothing found. It accepts a second param as the starting node to search.
234+
235+
<table>
236+
<tr>
237+
<th align="center">params</th>
238+
<th align="center">return</th>
239+
<th align="center">runtime</th>
240+
</tr>
241+
<tr>
242+
<td>
212243
cb: (node: DoublyLinkedListNode&lt;T&gt;) => boolean
244+
<br />
245+
<i>startingNode: DoublyLinkedListNode&lt;T&gt;</i>
213246
</td>
214247
<td align="center">
215248
<a href="#doublylinkedlistnodet">DoublyLinkedListNode&lt;T&gt;</a>
@@ -535,6 +568,19 @@ console.log(doublyLinkedList.head()); // null
535568
console.log(doublyLinkedList.tail()); // null
536569
```
537570

571+
### DoublyLinkedList.fromArray(values)
572+
creates a doubly linked list from an array.
573+
574+
##### JS
575+
```js
576+
const dll = DoublyLinkedList.fromArray([1, 2, 3, 4, 5]);
577+
```
578+
579+
##### TS
580+
```js
581+
const dll = DoublyLinkedList.fromArray<number>([1, 2, 3, 4, 5]);
582+
```
583+
538584
### DoublyLinkedListNode&lt;T&gt;
539585

540586
#### new DoublyLinkedListNode&lt;T&gt;(value, prev, next)

LinkedList.md

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* [.insertLast(value[, startingNode])](#insertlastvalue-startingnode)
1313
* [.insertAt(position, value)](#insertatposition-value)
1414
* [.forEach(cb)](#foreachcb)
15-
* [.find(cb)](#findcb)
15+
* [.find(cb[, startingNode])](#findcb-startingnode)
1616
* [.filter(cb)](#filtercb)
1717
* [.toArray()](#toarray)
1818
* [.isEmpty()](#isempty)
@@ -23,6 +23,7 @@
2323
* [.removeAt(position)](#removeatposition)
2424
* [.removeEach(cb)](#removeeachcb)
2525
* [.clear()](#clear)
26+
* [LinkedList.fromArray(values)](#linkedlistfromarrayvalues)
2627
* [LinkedListNode](#linkedlistnode)
2728

2829
## install
@@ -83,7 +84,7 @@ console.log(linkedList.insertFirst(1).getValue()); // 1
8384
```
8485

8586
### .insertLast(value[, startingNode])
86-
inserts a node at the end of the list. it accepts an optional second param as the starting node which can be used to insert in O(1) runtime by passing in last inserted node.
87+
inserts a node at the end of the list. it accepts an optional second param as the starting node which can be used to insert in O(1) runtime.
8788

8889
<table>
8990
<tr>
@@ -92,7 +93,11 @@ inserts a node at the end of the list. it accepts an optional second param as th
9293
<th align="center">runtime</th>
9394
</tr>
9495
<tr>
95-
<td align="center">value: T</td>
96+
<td>
97+
value: T
98+
<br />
99+
<i>startingNode: LinkedListNode&lt;T&gt;</i>
100+
</td>
96101
<td align="center"><a href="#linkedlistnodet">LinkedListNode&lt;T&gt;</a></td>
97102
<td>
98103
O(n) | O(1) with last inserted node passed
@@ -167,8 +172,8 @@ linkedList.forEach(
167172
*/
168173
```
169174

170-
### .find(cb)
171-
finds the first node that returns true from the callback or null if nothing found.
175+
### .find(cb[, startingNode])
176+
finds the first node that returns true from the callback or null if nothing found. It accepts a second param as the starting node to search.
172177

173178
<table>
174179
<tr>
@@ -177,8 +182,10 @@ finds the first node that returns true from the callback or null if nothing foun
177182
<th align="center">runtime</th>
178183
</tr>
179184
<tr>
180-
<td align="center">
185+
<td>
181186
cb: (node: LinkedListNode&lt;T&gt;) => boolean
187+
<br />
188+
<i>startingNode: LinkedListNode&lt;T&gt;</i>
182189
</td>
183190
<td align="center"><a href="#linkedlistnodet">LinkedListNode&lt;T&gt;</a></td>
184191
<td align="center">O(n)</td>
@@ -407,6 +414,19 @@ console.log(linkedList.count()); // 0
407414
console.log(linkedList.head()); // null
408415
```
409416

417+
### LinkedList.fromArray(values)
418+
creates a linked list from an array.
419+
420+
##### JS
421+
```js
422+
const ll = LinkedList.fromArray([1, 2, 3, 4, 5]);
423+
```
424+
425+
##### TS
426+
```js
427+
const ll = LinkedList.fromArray<number>([1, 2, 3, 4, 5]);
428+
```
429+
410430
### LinkedListNode&lt;T&gt;
411431

412432
#### new LinkedListNode&lt;T&gt;(value, next)

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@datastructures-js/linked-list",
3-
"version": "5.1.1",
3+
"version": "5.2.0",
44
"description": "a javascript implementation of LinkedList & DoublyLinkedList",
55
"main": "index.js",
66
"scripts": {
@@ -35,8 +35,5 @@
3535
"grunt-mocha-test": "^0.13.3",
3636
"istanbul": "^0.4.5",
3737
"mocha": "^6.2.2"
38-
},
39-
"dependencies": {
40-
"@datastructures-js/binary-search-tree": "^4.1.0"
4138
}
4239
}

src/doublyLinkedList.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ export class DoublyLinkedList<T> {
1212
removeEach(cb: (node: DoublyLinkedListNode<T>, position: number) => boolean): number;
1313
forEach(cb: (node: DoublyLinkedListNode<T>, position: number) => void): void;
1414
forEachReverse(cb: (node: DoublyLinkedListNode<T>, position: number) => void): void;
15-
find(cb: (node: DoublyLinkedListNode<T>) => boolean): DoublyLinkedListNode<T>;
15+
find(cb: (node: DoublyLinkedListNode<T>, startingNode?: DoublyLinkedListNode<T>) => boolean): DoublyLinkedListNode<T>;
16+
findReverse(cb: (node: DoublyLinkedListNode<T>, startingNode?: DoublyLinkedListNode<T>) => boolean): DoublyLinkedListNode<T>;
1617
filter(cb: (node: DoublyLinkedListNode<T>, position: number) => boolean): DoublyLinkedList<T>;
1718
head(): DoublyLinkedListNode<T>;
1819
tail(): DoublyLinkedListNode<T>;
1920
count(): number;
2021
toArray(): T[];
2122
isEmpty(): boolean;
2223
clear(): void;
24+
static fromArray<T>(values: T[]): DoublyLinkedList<T>;
2325
}

src/doublyLinkedList.js

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,19 @@ class DoublyLinkedList {
267267
* Finds a node in the list using a callback
268268
* @public
269269
* @param {function} cb
270+
* @param {DoublyLinkedListNode} [startingNode]
270271
* @returns {DoublyLinkedListNode}
271272
*/
272-
find(cb) {
273+
find(cb, startingNode = this._head) {
273274
if (typeof cb !== 'function') {
274275
throw new Error('.find(cb) expects a callback');
275276
}
276277

277-
let current = this._head;
278+
if (startingNode && !(startingNode instanceof DoublyLinkedListNode)) {
279+
throw new Error('.find(cb) expects to start from a DoublyLinkedListNode');
280+
}
281+
282+
let current = startingNode;
278283
while (current instanceof DoublyLinkedListNode) {
279284
if (cb(current)) {
280285
return current;
@@ -284,6 +289,32 @@ class DoublyLinkedList {
284289
return null;
285290
}
286291

292+
/**
293+
* Finds a node in the list using a callback in reverse order
294+
* @public
295+
* @param {function} cb
296+
* @param {DoublyLinkedListNode} [startingNode]
297+
* @returns {DoublyLinkedListNode}
298+
*/
299+
findReverse(cb, startingNode = this._tail) {
300+
if (typeof cb !== 'function') {
301+
throw new Error('.findReverse(cb) expects a callback');
302+
}
303+
304+
if (startingNode && !(startingNode instanceof DoublyLinkedListNode)) {
305+
throw new Error('.findReverse(cb) expects to start from a DoublyLinkedListNode');
306+
}
307+
308+
let current = startingNode;
309+
while (current instanceof DoublyLinkedListNode) {
310+
if (cb(current)) {
311+
return current;
312+
}
313+
current = current.getPrev();
314+
}
315+
return null;
316+
}
317+
287318
/**
288319
* Filters the list based on a callback.
289320
* @public
@@ -359,6 +390,25 @@ class DoublyLinkedList {
359390
this._tail = null;
360391
this._count = 0;
361392
}
393+
394+
/**
395+
* Creates a doubly linked list from an array
396+
* @public
397+
* @static
398+
* @param {array} values
399+
* @return {DoublyLinkedList}
400+
*/
401+
static fromArray(values) {
402+
if (!Array.isArray(values)) {
403+
throw new Error('cannot create DoublyLinkedList from none-array values');
404+
}
405+
406+
const doublyLinkedList = new DoublyLinkedList();
407+
values.forEach((value) => {
408+
doublyLinkedList.insertLast(value);
409+
});
410+
return doublyLinkedList;
411+
}
362412
}
363413

364414
exports.DoublyLinkedList = DoublyLinkedList;

src/linkedList.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ export class LinkedList<T> {
1717
toArray(): T[];
1818
isEmpty(): boolean;
1919
clear(): void;
20+
static fromArray<T>(values: T[]): LinkedList<T>;
2021
}

src/linkedList.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,20 @@ class LinkedList {
211211
/**
212212
* Finds one node in the list based on a callback.
213213
* @public
214+
* @param {function} cb
215+
* @param {DoublyLinkedListNode} [startingNode]
214216
* @returns {LinkedListNode}
215217
*/
216-
find(cb) {
218+
find(cb, startingNode = this._head) {
217219
if (typeof cb !== 'function') {
218220
throw new Error('.find(cb) expects a callback');
219221
}
220222

221-
let current = this._head;
223+
if (startingNode && !(startingNode instanceof LinkedListNode)) {
224+
throw new Error('.find(cb) expects to start from a LinkedListNode');
225+
}
226+
227+
let current = startingNode;
222228
while (current instanceof LinkedListNode) {
223229
if (cb(current)) {
224230
return current;
@@ -294,6 +300,26 @@ class LinkedList {
294300
this._head = null;
295301
this._count = 0;
296302
}
303+
304+
/**
305+
* Creates a linked list from an array
306+
* @public
307+
* @static
308+
* @param {array} values
309+
* @return {LinkedList}
310+
*/
311+
static fromArray(values) {
312+
if (!Array.isArray(values)) {
313+
throw new Error('cannot create LinkedList from none-array values');
314+
}
315+
316+
const linkedList = new LinkedList();
317+
let lastInserted = null;
318+
values.forEach((value) => {
319+
lastInserted = linkedList.insertLast(value, lastInserted);
320+
});
321+
return linkedList;
322+
}
297323
}
298324

299325
exports.LinkedList = LinkedList;

0 commit comments

Comments
 (0)