UNPKG

utilict

Version:

The JavaScript utility library for performing operations on all data types and data structures.

428 lines (427 loc) 13.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LinkedList = void 0; class LinkedListNode { constructor(value) { this.value = value; this.next = null; } getValue() { return this.value; } getNext() { return this.next; } setValue(value) { this.value = value; } setNext(next) { this.next = next; } } class LinkedList { constructor(list) { this.head = null; if (list) { this.constructFromArray(list); } } getHead() { return this.head; } setHead(value) { this.head = value; } /** * Construct the linked list from an array. * @param array * @returns The head of the linked list. */ constructFromArray(array) { let currentNode = null; this.setHead(null); if (array.length > 0) { for (const item of array) { const newNode = new LinkedListNode(item); if (this.getHead() === null) { this.setHead(newNode); currentNode = this.getHead(); } else { currentNode === null || currentNode === void 0 ? void 0 : currentNode.setNext(newNode); currentNode = newNode; } } } return this.head; } /** * Reverse the given linked list and returns the head of the reversed linked list. * @returns The head of the linked list. */ reverse() { if (this.head) { let previous = null; let current = this.head; let next = null; while (current !== null) { next = current.getNext(); current.setNext(previous); previous = current; current = next; } this.head = previous; } return this.head; } /** * Returns the linked list node count in the given list. * @returns The node count of the linked list. */ length() { if (this.head) { let length = 0; let current = this.head; while (current !== null) { length++; current = current.getNext(); } return length; } return 0; } /** * Sets the node with given value as a head of the list. * @param value * @returns The new head of the list. */ addFirst(value) { const newNode = new LinkedListNode(value); newNode.setNext(this.head); this.setHead(newNode); return this.head; } /** * Sets the node with the given value and adds to the last of the linked list. * @param value * @returns The head of the list. */ addLast(value) { const newNode = new LinkedListNode(value); if (this.head) { let currentNode = this.head; while ((currentNode === null || currentNode === void 0 ? void 0 : currentNode.getNext()) !== null) { if (currentNode) { currentNode = currentNode.getNext(); } } currentNode.setNext(newNode); } else { this.setHead(newNode); } return this.head; } addIndex(value, index) { const newNode = new LinkedListNode(value); let currentIndex = 0; let current = this.head; while (currentIndex < index - 1) { if (current) { current = current.getNext(); currentIndex++; } } if (current !== null) { newNode.setNext(current.getNext()); current.setNext(newNode); } return this.head; } /** * Adds the node at a given index. If index is not provided, then it will add node to the last of the linked list. * @param value * @param index * @returns The head of linked list. */ add(value, index) { if (index != null) { if (index === 0) { this.addFirst(value); } else if (index >= this.length()) { this.addLast(value); } else { this.addIndex(value, index); } } else { this.addLast(value); } return this.head; } /** * Removes the first node of the linked list. * @returns The head of the linked list. */ removeFirst() { if (this.head) { this.setHead(this.head.getNext()); return this.head; } return null; } /** * Removes the last node of the linked list. * @returns The head of the linked list. */ removeLast() { var _a; if (this.head) { if (this.head.getNext() === null) { this.head = null; } else { let currentNode = this.head; while ((currentNode === null || currentNode === void 0 ? void 0 : currentNode.getNext()) && ((_a = currentNode === null || currentNode === void 0 ? void 0 : currentNode.getNext()) === null || _a === void 0 ? void 0 : _a.getNext()) !== null) { if (currentNode) { currentNode = currentNode.getNext(); } } currentNode === null || currentNode === void 0 ? void 0 : currentNode.setNext(null); return this.head; } return this.head; } return null; } removeIndex(index) { if (this.head !== null) { let currentIndex = 0; let current = this.head; while (currentIndex < index - 1) { if (current) { current = current.getNext(); currentIndex++; } } if (current && (current === null || current === void 0 ? void 0 : current.getNext()) !== null) { const next = current.getNext(); if (next !== null) { current === null || current === void 0 ? void 0 : current.setNext(next === null || next === void 0 ? void 0 : next.getNext()); } } } return this.head; } /** * Removes the node at a given index. If index is not provided, it will remove a first node. * @param index * @returns The head of the linked list. */ remove(index) { if (index != null) { if (index < 0 || index >= this.length()) { throw new Error("Provided index is not in the range of the linked list !!"); } else if (index === 0) { this.removeFirst(); } else if (index === this.length() - 1) { this.removeLast(); } else { this.removeIndex(index); } } else { this.removeFirst(); } } /** * Gets the value of node at a given index. * @param index index * @returns Value of node at given index. */ getValue(index) { if (this.head) { if (index < 0 || index >= this.length()) { throw new Error("Provided index is not in the range of the linked list !!"); } let currentIndex = 0; let current = this.head; while (currentIndex < index) { if (current) { current = current.getNext(); currentIndex++; } } if (current) { return current.getValue(); } } return null; } /** * Update the value of node at a given index. * @param newValue New updated value. * @param index update index. * @returns The head of the linked list. */ update(newValue, index) { var _a; if (this.head) { if (index < 0 || index >= this.length()) { throw new Error("Provided index is not in the range of the linked list !!"); } if (index === 0) { (_a = this.getHead()) === null || _a === void 0 ? void 0 : _a.setValue(newValue); return this.getHead(); } let currentIndex = 0; let current = this.head; while (currentIndex < index) { if (current) { current = current.getNext(); currentIndex++; } } current === null || current === void 0 ? void 0 : current.setValue(newValue); return this.getHead(); } return null; } /** * Return the middle node of the linked list. * @returns The middle node of a given list. If linked list has even node count, it will return a node having index (length / 2) + 1. */ getMiddleNode() { if (this.head) { let slow = this.head; let fast = this.head; while (fast === null || fast === void 0 ? void 0 : fast.getNext()) { if (slow) { slow = slow.getNext(); } if (fast.getNext() !== null) { const next = fast.getNext(); if (next !== null) { fast = next.getNext(); } } } return slow; } return null; } /** * Return the middle node value. * @returns The middle node value of a given list. If linked list has even node count, it will return a node having index (length / 2) + 1. */ getMiddleValue() { if (this.head !== null) { const node = this.getMiddleNode(); return node === null || node === void 0 ? void 0 : node.getValue(); } return null; } rotate(position) { let current = this.head; let currentIndex = 0; while (currentIndex < position - 1) { if (current) { current = current.getNext(); currentIndex++; } } if (current) { const newHead = current.getNext(); current.setNext(null); current = newHead; while ((current === null || current === void 0 ? void 0 : current.getNext()) != null) { current = current.getNext(); } current === null || current === void 0 ? void 0 : current.setNext(this.head); this.head = newHead; } return this.head; } /** * Rotates the linked list to the right by given position. If position is negative, then it will rotate it towards left by given position. * @param pos Number of position by which the linked list to be rotated. If position is not provided, it will rotate it by 1. * @returns Head of linked list. */ rotateRight(pos) { if (this.head !== null) { const length = this.length(); const position = pos != null ? pos % length : 1; if (position === 0) { return this.head; } else if (position < 0) { this.rotate(Math.abs(position)); } else { this.rotate(length - position); } } return null; } /** * Rotates the linked list to the left by given position. If position is negative, then it will rotate it towards right by given position. * @param pos Number of position by which the linked list to be rotated. If position is not provided, it will rotate it by 1. * @returns Head of linked list. */ rotateLeft(pos) { if (this.head !== null) { const length = this.length(); const position = pos != null ? pos % length : 1; if (position === 0) { return this.head; } else if (position < 0) { this.rotate(length - Math.abs(position)); } else { this.rotate(position); } } return null; } /** * Concatenates second linked list into first one and return the first linked list. * @param list Second List * @returns First Linked List with merged list */ concat(list) { if (this.head !== null) { let current = this.head; while ((current === null || current === void 0 ? void 0 : current.getNext()) !== null) { if (current != null) { current = current.getNext(); } } current.setNext(list.head); return this; } else { this.head = list.head; return list; } } print() { if (this.head !== null) { const list = []; let current = this.head; while (current !== null) { list.push(current.getValue()); current = current.getNext(); } return list.join(" -> "); } return ""; } } exports.LinkedList = LinkedList;