117 lines
2.6 KiB
JavaScript
117 lines
2.6 KiB
JavaScript
|
const head = Symbol("head");
|
||
|
const tail = Symbol("tail");
|
||
|
|
||
|
class DoublyLinkedListNode {
|
||
|
constructor (data) {
|
||
|
this.data = data;
|
||
|
this.next = null;
|
||
|
this.previous = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export class DoublyLinkedList {
|
||
|
constructor () {
|
||
|
this[head] = null;
|
||
|
this[tail] = null;
|
||
|
}
|
||
|
|
||
|
add (data) {
|
||
|
const newNode = new DoublyLinkedListNode(data);
|
||
|
|
||
|
// special case: no nodes
|
||
|
if (this[head] === null) {
|
||
|
this[head] = newNode;
|
||
|
} else {
|
||
|
// link the current tail and new tail
|
||
|
this[tail].next = newNode;
|
||
|
newNode.previous = this[tail];
|
||
|
}
|
||
|
|
||
|
// re-assign the tail
|
||
|
this[tail] = newNode;
|
||
|
}
|
||
|
|
||
|
get (index) {
|
||
|
if ( ! Number(index) < 0) {
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
let current = this[head];
|
||
|
let i = 0;
|
||
|
|
||
|
while ((current !== null) && (i < index)) {
|
||
|
current = current.next;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
return current !== null
|
||
|
? current.data
|
||
|
: undefined;
|
||
|
}
|
||
|
|
||
|
remove (index) {
|
||
|
if ((this[head] === null) || (index < 0)) {
|
||
|
throw new RangeError(`Index ${index} does not exist in the list.`);
|
||
|
}
|
||
|
|
||
|
// special case: removing the first node
|
||
|
if (index === 0) {
|
||
|
const data = this[head].data;
|
||
|
this[head] = this[head].next;
|
||
|
|
||
|
// Only one node
|
||
|
if (this[head] === null) {
|
||
|
this[tail] = null;
|
||
|
} else {
|
||
|
this[head].previous = null;
|
||
|
}
|
||
|
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
let current = this[head];
|
||
|
let i = 0;
|
||
|
while ((current !== null) && (i < index)) {
|
||
|
current = current.next;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
// If node was found remove it
|
||
|
if (current !== null) {
|
||
|
current.previous.next = current.next;
|
||
|
|
||
|
// last node
|
||
|
if (this[tail] === current) {
|
||
|
this[tail] = current.previous;
|
||
|
} else {
|
||
|
current.next.previous = current.previous;
|
||
|
}
|
||
|
|
||
|
return current.data;
|
||
|
}
|
||
|
|
||
|
throw new RangeError(`Index ${index} does not exist in the list.`);
|
||
|
}
|
||
|
|
||
|
*values () {
|
||
|
let current = this[head];
|
||
|
|
||
|
while (current !== null) {
|
||
|
yield current.data;
|
||
|
current = current.next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*reverse () {
|
||
|
let current = this[tail];
|
||
|
|
||
|
while (current !== null) {
|
||
|
yield current.data;
|
||
|
current = current.previous;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Symbol.iterator] () {
|
||
|
return this.values();
|
||
|
}
|
||
|
}
|