typescript-collections
Version:
A complete, fully tested data structure library written in TypeScript.
381 lines • 13.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var util = require("./util");
var arrays = require("./arrays");
var LinkedList = /** @class */ (function () {
/**
* Creates an empty Linked List.
* @class A linked list is a data structure consisting of a group of nodes
* which together represent a sequence.
* @constructor
*/
function LinkedList() {
/**
* First node in the list
* @type {Object}
* @private
*/
this.firstNode = null;
/**
* Last node in the list
* @type {Object}
* @private
*/
this.lastNode = null;
/**
* Number of elements in the list
* @type {number}
* @private
*/
this.nElements = 0;
}
/**
* Adds an element to this list.
* @param {Object} item element to be added.
* @param {number=} index optional index to add the element. If no index is specified
* the element is added to the end of this list.
* @return {boolean} true if the element was added or false if the index is invalid
* or if the element is undefined.
*/
LinkedList.prototype.add = function (item, index) {
if (util.isUndefined(index)) {
index = this.nElements;
}
if (index < 0 || index > this.nElements || util.isUndefined(item)) {
return false;
}
var newNode = this.createNode(item);
if (this.nElements === 0 || this.lastNode === null) {
// First node in the list.
this.firstNode = newNode;
this.lastNode = newNode;
}
else if (index === this.nElements) {
// Insert at the end.
this.lastNode.next = newNode;
this.lastNode = newNode;
}
else if (index === 0) {
// Change first node.
newNode.next = this.firstNode;
this.firstNode = newNode;
}
else {
var prev = this.nodeAtIndex(index - 1);
if (prev === null) {
return false;
}
newNode.next = prev.next;
prev.next = newNode;
}
this.nElements++;
return true;
};
/**
* Returns the first element in this list.
* @return {*} the first element of the list or undefined if the list is
* empty.
*/
LinkedList.prototype.first = function () {
if (this.firstNode !== null) {
return this.firstNode.element;
}
return undefined;
};
/**
* Returns the last element in this list.
* @return {*} the last element in the list or undefined if the list is
* empty.
*/
LinkedList.prototype.last = function () {
if (this.lastNode !== null) {
return this.lastNode.element;
}
return undefined;
};
/**
* Returns the element at the specified position in this list.
* @param {number} index desired index.
* @return {*} the element at the given index or undefined if the index is
* out of bounds.
*/
LinkedList.prototype.elementAtIndex = function (index) {
var node = this.nodeAtIndex(index);
if (node === null) {
return undefined;
}
return node.element;
};
/**
* Returns the index in this list of the first occurrence of the
* specified element, or -1 if the List does not contain this element.
* <p>If the elements inside this list are
* not comparable with the === operator a custom equals function should be
* provided to perform searches, the function must receive two arguments and
* return true if they are equal, false otherwise. Example:</p>
*
* <pre>
* const petsAreEqualByName = function(pet1, pet2) {
* return pet1.name === pet2.name;
* }
* </pre>
* @param {Object} item element to search for.
* @param {function(Object,Object):boolean=} equalsFunction Optional
* function used to check if two elements are equal.
* @return {number} the index in this list of the first occurrence
* of the specified element, or -1 if this list does not contain the
* element.
*/
LinkedList.prototype.indexOf = function (item, equalsFunction) {
var equalsF = equalsFunction || util.defaultEquals;
if (util.isUndefined(item)) {
return -1;
}
var currentNode = this.firstNode;
var index = 0;
while (currentNode !== null) {
if (equalsF(currentNode.element, item)) {
return index;
}
index++;
currentNode = currentNode.next;
}
return -1;
};
/**
* Returns true if this list contains the specified element.
* <p>If the elements inside the list are
* not comparable with the === operator a custom equals function should be
* provided to perform searches, the function must receive two arguments and
* return true if they are equal, false otherwise. Example:</p>
*
* <pre>
* const petsAreEqualByName = function(pet1, pet2) {
* return pet1.name === pet2.name;
* }
* </pre>
* @param {Object} item element to search for.
* @param {function(Object,Object):boolean=} equalsFunction Optional
* function used to check if two elements are equal.
* @return {boolean} true if this list contains the specified element, false
* otherwise.
*/
LinkedList.prototype.contains = function (item, equalsFunction) {
return (this.indexOf(item, equalsFunction) >= 0);
};
/**
* Removes the first occurrence of the specified element in this list.
* <p>If the elements inside the list are
* not comparable with the === operator a custom equals function should be
* provided to perform searches, the function must receive two arguments and
* return true if they are equal, false otherwise. Example:</p>
*
* <pre>
* const petsAreEqualByName = function(pet1, pet2) {
* return pet1.name === pet2.name;
* }
* </pre>
* @param {Object} item element to be removed from this list, if present.
* @return {boolean} true if the list contained the specified element.
*/
LinkedList.prototype.remove = function (item, equalsFunction) {
var equalsF = equalsFunction || util.defaultEquals;
if (this.nElements < 1 || util.isUndefined(item)) {
return false;
}
var previous = null;
var currentNode = this.firstNode;
while (currentNode !== null) {
if (equalsF(currentNode.element, item)) {
if (previous === null) {
this.firstNode = currentNode.next;
if (currentNode === this.lastNode) {
this.lastNode = null;
}
}
else if (currentNode === this.lastNode) {
this.lastNode = previous;
previous.next = currentNode.next;
currentNode.next = null;
}
else {
previous.next = currentNode.next;
currentNode.next = null;
}
this.nElements--;
return true;
}
previous = currentNode;
currentNode = currentNode.next;
}
return false;
};
/**
* Removes all of the elements from this list.
*/
LinkedList.prototype.clear = function () {
this.firstNode = null;
this.lastNode = null;
this.nElements = 0;
};
/**
* Returns true if this list is equal to the given list.
* Two lists are equal if they have the same elements in the same order.
* @param {LinkedList} other the other list.
* @param {function(Object,Object):boolean=} equalsFunction optional
* function used to check if two elements are equal. If the elements in the lists
* are custom objects you should provide a function, otherwise
* the === operator is used to check equality between elements.
* @return {boolean} true if this list is equal to the given list.
*/
LinkedList.prototype.equals = function (other, equalsFunction) {
var eqF = equalsFunction || util.defaultEquals;
if (!(other instanceof LinkedList)) {
return false;
}
if (this.size() !== other.size()) {
return false;
}
return this.equalsAux(this.firstNode, other.firstNode, eqF);
};
/**
* @private
*/
LinkedList.prototype.equalsAux = function (n1, n2, eqF) {
while (n1 !== null && n2 !== null) {
if (!eqF(n1.element, n2.element)) {
return false;
}
n1 = n1.next;
n2 = n2.next;
}
return true;
};
/**
* Removes the element at the specified position in this list.
* @param {number} index given index.
* @return {*} removed element or undefined if the index is out of bounds.
*/
LinkedList.prototype.removeElementAtIndex = function (index) {
if (index < 0 || index >= this.nElements || this.firstNode === null || this.lastNode === null) {
return undefined;
}
var element;
if (this.nElements === 1) {
//First node in the list.
element = this.firstNode.element;
this.firstNode = null;
this.lastNode = null;
}
else {
var previous = this.nodeAtIndex(index - 1);
if (previous === null) {
element = this.firstNode.element;
this.firstNode = this.firstNode.next;
}
else if (previous.next === this.lastNode) {
element = this.lastNode.element;
this.lastNode = previous;
}
if (previous !== null && previous.next !== null) {
element = previous.next.element;
previous.next = previous.next.next;
}
}
this.nElements--;
return element;
};
/**
* Executes the provided function once for each element present in this list in order.
* @param {function(Object):*} callback function to execute, it is
* invoked with one argument: the element value, to break the iteration you can
* optionally return false.
*/
LinkedList.prototype.forEach = function (callback) {
var currentNode = this.firstNode;
while (currentNode !== null) {
if (callback(currentNode.element) === false) {
break;
}
currentNode = currentNode.next;
}
};
/**
* Reverses the order of the elements in this linked list (makes the last
* element first, and the first element last).
*/
LinkedList.prototype.reverse = function () {
var previous = null;
var current = this.firstNode;
var temp = null;
while (current !== null) {
temp = current.next;
current.next = previous;
previous = current;
current = temp;
}
temp = this.firstNode;
this.firstNode = this.lastNode;
this.lastNode = temp;
};
/**
* Returns an array containing all of the elements in this list in proper
* sequence.
* @return {Array.<*>} an array containing all of the elements in this list,
* in proper sequence.
*/
LinkedList.prototype.toArray = function () {
var array = [];
var currentNode = this.firstNode;
while (currentNode !== null) {
array.push(currentNode.element);
currentNode = currentNode.next;
}
return array;
};
/**
* Returns the number of elements in this list.
* @return {number} the number of elements in this list.
*/
LinkedList.prototype.size = function () {
return this.nElements;
};
/**
* Returns true if this list contains no elements.
* @return {boolean} true if this list contains no elements.
*/
LinkedList.prototype.isEmpty = function () {
return this.nElements <= 0;
};
LinkedList.prototype.toString = function () {
return arrays.toString(this.toArray());
};
/**
* @private
*/
LinkedList.prototype.nodeAtIndex = function (index) {
if (index < 0 || index >= this.nElements) {
return null;
}
if (index === (this.nElements - 1)) {
return this.lastNode;
}
var node = this.firstNode;
for (var i = 0; i < index && node !== null; i++) {
node = node.next;
}
return node;
};
/**
* @private
*/
LinkedList.prototype.createNode = function (item) {
return {
element: item,
next: null
};
};
return LinkedList;
}()); // End of linked list
exports.default = LinkedList;
//# sourceMappingURL=LinkedList.js.map