container-doublylist
Version:
DoublyList implementation in JavaScript
229 lines (187 loc) • 4.96 kB
JavaScript
/**
* DOUBLY LIST Class
*
* @author Brice Chevalier
*
* @desc Doubly list data structure
*
* Method Time Complexity
* ___________________________________
*
* add (front and back) O(1)
* pop (front and back) O(1)
* remove by reference O(1)
* remove O(n)
* moveToBeginning O(1)
* moveToEnd O(1)
* clear O(n)
*
* Memory Complexity in O(n)
*/
function ListNode(obj, previous, next, container) {
this.object = obj;
this.previous = previous;
this.next = next;
this.container = container;
}
function DoublyList() {
this.first = null;
this.last = null;
this.length = 0;
}
module.exports = DoublyList;
DoublyList.prototype.addFront = function (obj) {
var newNode = new ListNode(obj, null, this.first, this);
if (this.first === null) {
this.first = newNode;
this.last = newNode;
} else {
this.first.previous = newNode;
this.first = newNode;
}
this.length += 1;
return newNode;
};
DoublyList.prototype.add = DoublyList.prototype.addFront;
DoublyList.prototype.addBack = function (obj) {
var newNode = new ListNode(obj, this.last, null, this);
if (this.first === null) {
this.first = newNode;
this.last = newNode;
} else {
this.last.next = newNode;
this.last = newNode;
}
this.length += 1;
return newNode;
};
DoublyList.prototype.popFront = function () {
var object = this.first.object;
this.removeByReference(this.first);
return object;
};
DoublyList.prototype.pop = DoublyList.prototype.popFront;
DoublyList.prototype.popBack = function () {
var object = this.last.object;
this.removeByReference(this.last);
return object;
};
DoublyList.prototype.addBefore = function (node, obj) {
var newNode = new ListNode(obj, node.previous, node, this);
if (node.previous !== null) {
node.previous.next = newNode;
}
node.previous = newNode;
if (this.first === node) {
this.first = newNode;
}
this.length += 1;
return newNode;
};
DoublyList.prototype.addAfter = function (node, obj) {
var newNode = new ListNode(obj, node, node.next, this);
if (node.next !== null) {
node.next.previous = newNode;
}
node.next = newNode;
if (this.last === node) {
this.last = newNode;
}
this.length += 1;
return newNode;
};
DoublyList.prototype.moveToTheBeginning = function (node) {
if (!node || node.container !== this) {
return false;
}
if (node.previous === null) {
// node is already the first one
return true;
}
// Connecting previous node to next node
node.previous.next = node.next;
if (this.last === node) {
this.last = node.previous;
} else {
// Connecting next node to previous node
node.next.previous = node.previous;
}
// Adding at the beginning
node.previous = null;
node.next = this.first;
node.next.previous = node;
this.first = node;
return true;
};
DoublyList.prototype.moveToTheEnd = function (node) {
if (!node || node.container !== this) {
return false;
}
if (node.next === null) {
// node is already the last one
return true;
}
// Connecting next node to previous node
node.next.previous = node.previous;
if (this.first === node) {
this.first = node.next;
} else {
// Connecting previous node to next node
node.previous.next = node.next;
}
// Adding at the end
node.next = null;
node.previous = this.last;
node.previous.next = node;
this.last = node;
return true;
};
DoublyList.prototype.removeByReference = function (node) {
if (node.container !== this) {
console.warn('[DoublyList.removeByReference] Trying to remove a node that does not belong to the list');
return node;
}
if (node.next === null) {
this.last = node.previous;
} else {
node.next.previous = node.previous;
}
if (node.previous === null) {
this.first = node.next;
} else {
node.previous.next = node.next;
}
node.container = null;
this.length -= 1;
return null;
};
DoublyList.prototype.remove = function (object) {
for (var node = this.first; node !== null; node = node.next) {
if (node.object === object) {
this.removeByReference(node);
return true;
}
}
return false;
};
DoublyList.prototype.clear = function () {
// Making sure that nodes containers are being resetted
for (var node = this.first; node !== null; node = node.next) {
node.container = null;
}
this.first = null;
this.last = null;
this.length = 0;
};
DoublyList.prototype.forEach = function (processingFunc, params) {
for (var node = this.first; node; node = node.next) {
processingFunc(node.object, params);
}
};
DoublyList.prototype.toArray = function () {
var objects = [];
for (var node = this.first; node !== null; node = node.next) {
objects.push(node.object);
}
return objects;
};