this.compare = new Comparator(comparatorFunction); }
/** * @param {*} value * @return {DoublyLinkedList} */ prepend(value) { // Make new node to be a head. const newNode = new DoublyLinkedListNode(value, this.head);
// If there is head, then it won't be head anymore. // Therefore, make its previous reference to be new node (new head). // Then mark the new node as head. if (this.head) { this.head.previous = newNode; } this.head = newNode;
// If there is no tail yet let's make new node a tail. if (!this.tail) { this.tail = newNode; }
return this; }
/** * @param {*} value * @return {DoublyLinkedList} */ append(value) { const newNode = new DoublyLinkedListNode(value);
// If there is no head yet let's make new node a head. if (!this.head) { this.head = newNode; this.tail = newNode;
return this; }
// Attach new node to the end of linked list. this.tail.next = newNode;
// Attach current tail to the new node's previous reference. newNode.previous = this.tail;
// Set new node to be the tail of linked list. this.tail = newNode;
return this; }
/** * @param {*} value * @return {DoublyLinkedListNode} */ delete(value) { if (!this.head) { return null; }
let deletedNode = null; let currentNode = this.head;
while (currentNode) { if (this.compare.equal(currentNode.value, value)) { deletedNode = currentNode;
if (deletedNode === this.head) { // If HEAD is going to be deleted...
// Set head to second node, which will become new head. this.head = deletedNode.next;
// Set new head's previous to null. if (this.head) { this.head.previous = null; }
// If all the nodes in list has same value that is passed as argument // then all nodes will get deleted, therefore tail needs to be updated. if (deletedNode === this.tail) { this.tail = null; } } else if (deletedNode === this.tail) { // If TAIL is going to be deleted...
// Set tail to second last node, which will become new tail. this.tail = deletedNode.previous; this.tail.next = null; } else { // If MIDDLE node is going to be deleted... const previousNode = deletedNode.previous; const nextNode = deletedNode.next;
while (currentNode) { // If callback is specified then try to find node by callback. if (callback && callback(currentNode.value)) { return currentNode; }
// If value is specified then try to compare by value.. if (value !== undefined && this.compare.equal(currentNode.value, value)) { return currentNode; }
currentNode = currentNode.next; }
return null; }
/** * @return {DoublyLinkedListNode} */ deleteTail() { if (!this.tail) { // No tail to delete. return null; }
if (this.head === this.tail) { // There is only one node in linked list. const deletedTail = this.tail; this.head = null; this.tail = null;
return deletedTail; }
// If there are many nodes in linked list... const deletedTail = this.tail;
let currentNode = this.head; while (currentNode) { nodes.push(currentNode); currentNode = currentNode.next; }
return nodes; }
/** * @param {*[]} values - Array of values that need to be converted to linked list. * @return {DoublyLinkedList} */ fromArray(values) { values.forEach(value => this.append(value));