utilict
Version:
The JavaScript utility library for performing operations on all data types and data structures.
428 lines (427 loc) • 13.5 kB
JavaScript
"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;