1
0
Fork 0
computer-science-in-javascript/src/structures/circular-doubly-linked-list.js

131 lines
3.1 KiB
JavaScript

const head = Symbol("head");
const tail = Symbol("tail");
class CircularDoublyLinkedListNode {
constructor (data) {
this.data = data;
this.next = null;
this.previous = null;
}
}
export class CircularDoublyLinkedList {
constructor () {
this[head] = null;
this[tail] = null;
}
add (data) {
const newNode = new CircularDoublyLinkedListNode(data);
// Special case: no items in the list
if (this[head] === null) {
this[head] = newNode;
newNode.next = newNode;
newNode.previous = newNode;
} else {
const tail = this[head].previous;
tail.next = newNode;
newNode.previous = tail;
newNode.next = this[head];
this[head].previous = newNode;
}
}
get (index) {
if ( ! Number(index) < 0) {
return undefined;
}
let current = this[head];
let i = 0;
do {
if (i === index) {
return current.data;
}
current = current.next;
i++;
} while ((current !== this[head]) && (i <= index));
return undefined;
}
remove (index) {
if ((this[head] === null) || (index < 0)) {
throw new RangeError(`Index ${index} does not exist in the list.`);
}
let current = this[head];
// Removing the first node
if (index === 0) {
if (current.next === this[head]) {
this[head] = null;
} else {
const tail = this[head].previous;
// Set the tail to point to the second item in the list
// and point the new item to the tail
tail.next = current.next;
current.next.previous = tail;
this[head] = tail.next;
}
return current.data;
}
let i = 0;
do {
current = current.next;
i++;
} while ((current !== this[head]) && (i < index));
if (current !== this[head]) {
// skip over the node to remove it
current.previous.next = current.next;
current.next.previous = current.previous;
return current.data;
}
throw new RangeError(`Index ${index} does not exist in the list.`);
}
*values () {
// list is empty
if (this[head] !== null) {
// only one node
if (this[head].next === this[head]) {
yield this[head].data;
} else {
let current = this[head];
do {
yield current.data;
current = current.next;
} while (current !== this[head]);
}
}
}
*circularValues () {
if (this[head] !== null) {
let current = this[head];
// infinite loop
while (true) {
yield current.data;
current = current.next;
}
}
}
[Symbol.iterator] () {
return this.values();
}
}