typescript-ds-lib
Version:
A collection of TypeScript data structure implementations
304 lines • 8.49 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LinkedList = void 0;
const base_collection_1 = require("./base-collection");
const utils_1 = require("./utils");
class Node {
value;
next;
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList extends base_collection_1.BaseCollection {
head;
tail;
length;
constructor() {
super();
this.head = null;
this.tail = null;
this.length = 0;
}
/**
* Returns the first element in the list without removing it, or undefined if list is empty
*/
front() {
return this.head?.value;
}
/**
* Returns the last element in the list without removing it, or undefined if list is empty
*/
back() {
return this.tail?.value;
}
/**
* Adds an element to the end of the list
*/
pushBack(element) {
const newNode = new Node(element);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
}
else {
this.tail.next = newNode;
this.tail = newNode;
}
this.length++;
}
/**
* Adds an element to the front of the list
*/
pushFront(element) {
const newNode = new Node(element);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
}
else {
newNode.next = this.head;
this.head = newNode;
}
this.length++;
}
/**
* Removes and returns the last element from the list, or undefined if list is empty
*/
popBack() {
if (!this.head) {
return undefined;
}
if (this.length === 1) {
const value = this.head.value;
this.head = null;
this.tail = null;
this.length = 0;
return value;
}
let current = this.head;
while (current?.next !== this.tail) {
current = current.next;
}
const value = this.tail.value;
current.next = null;
this.tail = current;
this.length--;
return value;
}
/**
* Removes and returns the first element from the list, or undefined if list is empty
*/
popFront() {
if (!this.head) {
return undefined;
}
const value = this.head.value;
this.head = this.head.next;
this.length--;
if (this.length === 0) {
this.tail = null;
}
return value;
}
/**
* Inserts an element at the specified position. Returns true if successful, false if position is invalid
*/
insert(element, position) {
if (position < 0 || position > this.length) {
return false;
}
if (position === 0) {
this.pushFront(element);
return true;
}
if (position === this.length) {
this.pushBack(element);
return true;
}
const newNode = new Node(element);
let current = this.head;
let prev = null;
let index = 0;
while (index < position) {
prev = current;
current = current.next;
index++;
}
prev.next = newNode;
newNode.next = current;
this.length++;
return true;
}
/**
* Inserts an element before the first element that satisfies the condition. Returns true if successful, false if no matching element found
*/
insertBefore(element, condition) {
if (!this.head) {
return false;
}
if (condition(this.head.value)) {
this.pushFront(element);
return true;
}
let current = this.head;
while (current?.next !== null) {
if (condition(current.next.value)) {
const newNode = new Node(element);
newNode.next = current.next;
current.next = newNode;
this.length++;
return true;
}
current = current.next;
}
return false;
}
/**
* Inserts an element after the first element that satisfies the condition. Returns true if successful, false if no matching element found
*/
insertAfter(element, condition) {
let current = this.head;
while (current !== null) {
if (condition(current.value)) {
const newNode = new Node(element);
newNode.next = current.next;
current.next = newNode;
if (current === this.tail) {
this.tail = newNode;
}
this.length++;
return true;
}
current = current.next;
}
return false;
}
/**
* Removes the first element that satisfies the predicate. Returns true if an element was removed, false otherwise.
*/
removeIf(condition) {
let current = this.head;
let prev = null;
while (current !== null) {
if (condition(current.value)) {
if (prev === null) {
this.head = current.next;
}
else {
prev.next = current.next;
}
if (current === this.tail) {
this.tail = prev;
}
this.length--;
return true;
}
prev = current;
current = current.next;
}
return false;
}
/**
* Removes and returns the element at the specified position. Returns undefined if position is invalid
*/
removeAt(position) {
if (position < 0 || position >= this.length) {
return undefined;
}
let current = this.head;
if (position === 0) {
this.head = current.next;
if (this.length === 1) {
this.tail = null;
}
this.length--;
return current.value;
}
let prev = null;
let index = 0;
while (index < position) {
prev = current;
current = current.next;
index++;
}
prev.next = current.next;
if (position === this.length - 1) {
this.tail = prev;
}
this.length--;
return current.value;
}
/**
* Executes a provided function once for each element in the list
*/
forEach(callback) {
let current = this.head;
while (current !== null) {
callback(current.value);
current = current.next;
}
}
/**
* Returns the element at the specified position without removing it. Returns undefined if position is invalid
*/
get(position) {
if (position < 0 || position >= this.length) {
return undefined;
}
// Optimize for front element
if (position === 0)
return this.head.value;
// Optimize for back element
if (position === this.length - 1)
return this.tail.value;
let current = this.head;
let index = 0;
while (index < position) {
current = current.next;
index++;
}
return current.value;
}
/**
* Returns true if the list is empty, false otherwise
*/
isEmpty() {
return this.length === 0;
}
/**
* Returns the number of elements in the list
*/
size() {
return this.length;
}
/**
* Removes all elements from the list
*/
clear() {
this.head = null;
this.tail = null;
this.length = 0;
}
/**
* Checks if two lists are equal.
*/
equals(other) {
if (!other || !(other instanceof LinkedList))
return false;
if (this.size() !== other.size())
return false;
let current = this.head;
let otherCurrent = other.head;
while (current !== null) {
if (!utils_1.Utils.equals(current.value, otherCurrent.value))
return false;
current = current.next;
otherCurrent = otherCurrent.next;
}
return true;
}
}
exports.LinkedList = LinkedList;
//# sourceMappingURL=linked-list.js.map