You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.2 KiB
JavaScript
113 lines
2.2 KiB
JavaScript
import defined from "./defined.js";
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function DoublyLinkedList() {
|
|
this.head = undefined;
|
|
this.tail = undefined;
|
|
this._length = 0;
|
|
}
|
|
|
|
Object.defineProperties(DoublyLinkedList.prototype, {
|
|
length: {
|
|
get: function () {
|
|
return this._length;
|
|
},
|
|
},
|
|
});
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function DoublyLinkedListNode(item, previous, next) {
|
|
this.item = item;
|
|
this.previous = previous;
|
|
this.next = next;
|
|
}
|
|
|
|
/**
|
|
* Adds the item to the end of the list
|
|
* @param {*} [item]
|
|
* @return {DoublyLinkedListNode}
|
|
*/
|
|
DoublyLinkedList.prototype.add = function (item) {
|
|
var node = new DoublyLinkedListNode(item, this.tail, undefined);
|
|
|
|
if (defined(this.tail)) {
|
|
this.tail.next = node;
|
|
this.tail = node;
|
|
} else {
|
|
this.head = node;
|
|
this.tail = node;
|
|
}
|
|
|
|
++this._length;
|
|
|
|
return node;
|
|
};
|
|
|
|
function remove(list, node) {
|
|
if (defined(node.previous) && defined(node.next)) {
|
|
node.previous.next = node.next;
|
|
node.next.previous = node.previous;
|
|
} else if (defined(node.previous)) {
|
|
// Remove last node
|
|
node.previous.next = undefined;
|
|
list.tail = node.previous;
|
|
} else if (defined(node.next)) {
|
|
// Remove first node
|
|
node.next.previous = undefined;
|
|
list.head = node.next;
|
|
} else {
|
|
// Remove last node in the linked list
|
|
list.head = undefined;
|
|
list.tail = undefined;
|
|
}
|
|
|
|
node.next = undefined;
|
|
node.previous = undefined;
|
|
}
|
|
|
|
/**
|
|
* Removes the given node from the list
|
|
* @param {DoublyLinkedListNode} node
|
|
*/
|
|
DoublyLinkedList.prototype.remove = function (node) {
|
|
if (!defined(node)) {
|
|
return;
|
|
}
|
|
|
|
remove(this, node);
|
|
|
|
--this._length;
|
|
};
|
|
|
|
/**
|
|
* Moves nextNode after node
|
|
* @param {DoublyLinkedListNode} node
|
|
* @param {DoublyLinkedListNode} nextNode
|
|
*/
|
|
DoublyLinkedList.prototype.splice = function (node, nextNode) {
|
|
if (node === nextNode) {
|
|
return;
|
|
}
|
|
|
|
// Remove nextNode, then insert after node
|
|
remove(this, nextNode);
|
|
|
|
var oldNodeNext = node.next;
|
|
node.next = nextNode;
|
|
|
|
// nextNode is the new tail
|
|
if (this.tail === node) {
|
|
this.tail = nextNode;
|
|
} else {
|
|
oldNodeNext.previous = nextNode;
|
|
}
|
|
|
|
nextNode.next = oldNodeNext;
|
|
nextNode.previous = node;
|
|
};
|
|
export default DoublyLinkedList;
|