UNPKG

lgrthms

Version:

Algorithms and data structures for your JavaScript and TypeScript projects 🧑‍💻

186 lines (185 loc) 5.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DoublyLinkedList = void 0; class Node { constructor(value) { this.value = value; this.next = null; this.prev = null; } } class DoublyLinkedList { constructor() { this._head = null; this._tail = null; this._length = 0; } get head() { return this._head; } get tail() { return this._tail; } get length() { return this._length; } // Best: O(1) time | O(1) space // Average: O(n) time | O(1) space get(index) { const node = this.getNode(index); return node ? node.value : undefined; } // Best: O(1) time | O(1) space // Average: O(n) time | O(1) space getNode(index) { const lastIndex = this._length - 1; if (index < 0 || index > lastIndex) { return; } if (index === lastIndex) { return this._tail; } let current = this._head; let currentIndex = 0; while (currentIndex < index) { current = current.next; currentIndex++; } return current || undefined; } // O(n) time | O(1) space find(predicate) { const node = this.findNode(predicate); return node ? node.value : undefined; } // O(n) time | O(1) space findNode(predicate) { let current = this._head; while (current) { if (predicate(current.value)) { return current; } current = current.next; } } // Best: O(1) time | O(1) space // Average: O(n) time | O(1) space insert(value, index) { const lastIndex = this._length - 1; if (index === undefined) { index = lastIndex + 1; } if (index < 0 || index > lastIndex + 1) { throw new Error('Cannot insert value, given index is out of bounds'); } if (index === 0) { return this.setHead(value); } if (index === lastIndex + 1) { return this.setTail(value); } const insertAfterIndex = index - 1; const insertAfterNode = this.getNode(insertAfterIndex); return this.insertAfter(value, insertAfterNode); } // O(1) time | O(1) space insertAfter(value, node) { const nodeToInsert = new Node(value); nodeToInsert.next = node.next; nodeToInsert.prev = node; node.next = nodeToInsert; if (nodeToInsert.next) { nodeToInsert.next.prev = nodeToInsert; } else { this._tail = nodeToInsert; } this._length++; return nodeToInsert; } // O(1) time | O(1) space insertBefore(value, node) { const nodeToInsert = new Node(value); nodeToInsert.prev = node.prev; nodeToInsert.next = node; node.prev = nodeToInsert; if (nodeToInsert.prev) { nodeToInsert.prev.next = nodeToInsert; } else { this._head = nodeToInsert; } this._length++; return nodeToInsert; } // O(n) time | O(1) space removeAtIndex(index) { const node = this.getNode(index); if (node) { return this.removeNode(node); } } // O(n) time | O(1) space removeWithValue(predicate) { let current = this._head; while (current) { const next = current.next; if (predicate(current.value)) { this.removeNode(current); } current = next; } } // O(1) time | O(1) space removeNode(node) { if (!node) { return; } if (node === this._head) { this._head = node.next; } if (node === this._tail) { this._tail = node.prev; } if (node.prev) { node.prev.next = node.next; } if (node.next) { node.next.prev = node.prev; } node.prev = null; node.next = null; this._length--; } // O(n) time | O(1) space forEach(callbackfn) { let current = this._head; while (current) { callbackfn(current.value); current = current.next; } } // O(1) time | O(1) space setHead(value) { if (!this._head) { const node = new Node(value); this._head = node; this._tail = node; this._length++; return node; } return this.insertBefore(value, this._head); } // O(1) time | O(1) space setTail(value) { if (!this._tail) { const node = new Node(value); this._head = node; this._tail = node; this._length++; return node; } return this.insertAfter(value, this._tail); } } exports.DoublyLinkedList = DoublyLinkedList;