lgrthms
Version:
Algorithms and data structures for your JavaScript and TypeScript projects 🧑💻
156 lines (155 loc) • 4.26 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SinglyLinkedList = void 0;
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class SinglyLinkedList {
constructor() {
this._head = null;
this._length = 0;
}
get head() {
return this._head;
}
get length() {
return this._length;
}
// O(n) time | O(1) space
get(index) {
const node = this.getNode(index);
return node ? node.value : undefined;
}
// O(n) time | O(1) space
getNode(index) {
const lastIndex = this._length - 1;
if (index < 0 || index > lastIndex) {
return;
}
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);
}
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;
node.next = nodeToInsert;
this._length++;
return nodeToInsert;
}
// O(n) time | O(1) space
removeAtIndex(index) {
const lastIndex = this._length - 1;
if (index < 0 || index > lastIndex) {
return;
}
let current = this._head;
let previous = null;
let currentIndex = 0;
while (currentIndex < index) {
previous = current;
current = current.next;
currentIndex++;
}
return this.remove(current, previous);
}
// O(n) time | O(1) space
removeWithValue(predicate) {
let current = this._head;
let previous = null;
while (current) {
if (predicate(current.value)) {
this.remove(current, previous);
}
else {
previous = current;
}
current = current.next;
}
}
// O(n) time | O(1) space
removeNode(node) {
if (!node) {
return;
}
let current = this._head;
let previous = null;
while (current) {
if (current === node) {
return this.remove(current, previous);
}
previous = current;
current = current.next;
}
}
// 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) {
const node = new Node(value);
node.next = this._head;
this._head = node;
this._length++;
return this._head;
}
// O(1) time | O(1) space
remove(node, previous) {
if (node === this._head) {
this._head = node.next;
}
else if (previous) {
previous.next = node.next;
}
else {
throw new Error('Cannot remove node, make sure to pass valid parameters');
}
this._length--;
}
}
exports.SinglyLinkedList = SinglyLinkedList;