UNPKG

@phosphor/collections

Version:
704 lines (703 loc) 20.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /*----------------------------------------------------------------------------- | Copyright (c) 2014-2017, PhosphorJS Contributors | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ var algorithm_1 = require("@phosphor/algorithm"); /** * A generic doubly-linked list. */ var LinkedList = /** @class */ (function () { /** * Construct a new linked list. */ function LinkedList() { this._first = null; this._last = null; this._size = 0; } Object.defineProperty(LinkedList.prototype, "isEmpty", { /** * Whether the list is empty. * * #### Complexity * Constant. */ get: function () { return this._size === 0; }, enumerable: true, configurable: true }); Object.defineProperty(LinkedList.prototype, "size", { /** * The size of the list. * * #### Complexity * `O(1)` * * #### Notes * This is equivalent to `length`. */ get: function () { return this._size; }, enumerable: true, configurable: true }); Object.defineProperty(LinkedList.prototype, "length", { /** * The length of the list. * * #### Complexity * Constant. * * #### Notes * This is equivalent to `size`. * * This property is deprecated. */ get: function () { return this._size; }, enumerable: true, configurable: true }); Object.defineProperty(LinkedList.prototype, "first", { /** * The first value in the list. * * This is `undefined` if the list is empty. * * #### Complexity * Constant. */ get: function () { return this._first ? this._first.value : undefined; }, enumerable: true, configurable: true }); Object.defineProperty(LinkedList.prototype, "last", { /** * The last value in the list. * * This is `undefined` if the list is empty. * * #### Complexity * Constant. */ get: function () { return this._last ? this._last.value : undefined; }, enumerable: true, configurable: true }); Object.defineProperty(LinkedList.prototype, "firstNode", { /** * The first node in the list. * * This is `null` if the list is empty. * * #### Complexity * Constant. */ get: function () { return this._first; }, enumerable: true, configurable: true }); Object.defineProperty(LinkedList.prototype, "lastNode", { /** * The last node in the list. * * This is `null` if the list is empty. * * #### Complexity * Constant. */ get: function () { return this._last; }, enumerable: true, configurable: true }); /** * Create an iterator over the values in the list. * * @returns A new iterator starting with the first value. * * #### Complexity * Constant. */ LinkedList.prototype.iter = function () { return new LinkedList.ForwardValueIterator(this._first); }; /** * Create a reverse iterator over the values in the list. * * @returns A new iterator starting with the last value. * * #### Complexity * Constant. */ LinkedList.prototype.retro = function () { return new LinkedList.RetroValueIterator(this._last); }; /** * Create an iterator over the nodes in the list. * * @returns A new iterator starting with the first node. * * #### Complexity * Constant. */ LinkedList.prototype.nodes = function () { return new LinkedList.ForwardNodeIterator(this._first); }; /** * Create a reverse iterator over the nodes in the list. * * @returns A new iterator starting with the last node. * * #### Complexity * Constant. */ LinkedList.prototype.retroNodes = function () { return new LinkedList.RetroNodeIterator(this._last); }; /** * Assign new values to the list, replacing all current values. * * @param values - The values to assign to the list. * * #### Complexity * Linear. */ LinkedList.prototype.assign = function (values) { var _this = this; this.clear(); algorithm_1.each(values, function (value) { _this.addLast(value); }); }; /** * Add a value to the end of the list. * * @param value - The value to add to the end of the list. * * #### Complexity * Constant. * * #### Notes * This is equivalent to `addLast`. */ LinkedList.prototype.push = function (value) { this.addLast(value); }; /** * Remove and return the value at the end of the list. * * @returns The removed value, or `undefined` if the list is empty. * * #### Complexity * Constant. * * #### Notes * This is equivalent to `removeLast`. */ LinkedList.prototype.pop = function () { return this.removeLast(); }; /** * Add a value to the beginning of the list. * * @param value - The value to add to the beginning of the list. * * #### Complexity * Constant. * * #### Notes * This is equivalent to `addFirst`. */ LinkedList.prototype.shift = function (value) { this.addFirst(value); }; /** * Remove and return the value at the beginning of the list. * * @returns The removed value, or `undefined` if the list is empty. * * #### Complexity * Constant. * * #### Notes * This is equivalent to `removeFirst`. */ LinkedList.prototype.unshift = function () { return this.removeFirst(); }; /** * Add a value to the beginning of the list. * * @param value - The value to add to the beginning of the list. * * @returns The list node which holds the value. * * #### Complexity * Constant. */ LinkedList.prototype.addFirst = function (value) { var node = new Private.LinkedListNode(this, value); if (!this._first) { this._first = node; this._last = node; } else { node.next = this._first; this._first.prev = node; this._first = node; } this._size++; return node; }; /** * Add a value to the end of the list. * * @param value - The value to add to the end of the list. * * @returns The list node which holds the value. * * #### Complexity * Constant. */ LinkedList.prototype.addLast = function (value) { var node = new Private.LinkedListNode(this, value); if (!this._last) { this._first = node; this._last = node; } else { node.prev = this._last; this._last.next = node; this._last = node; } this._size++; return node; }; /** * Insert a value before a specific node in the list. * * @param value - The value to insert before the reference node. * * @param ref - The reference node of interest. If this is `null`, * the value will be added to the beginning of the list. * * @returns The list node which holds the value. * * #### Notes * The reference node must be owned by the list. * * #### Complexity * Constant. */ LinkedList.prototype.insertBefore = function (value, ref) { if (!ref || ref === this._first) { return this.addFirst(value); } if (!(ref instanceof Private.LinkedListNode) || ref.list !== this) { throw new Error('Reference node is not owned by the list.'); } var node = new Private.LinkedListNode(this, value); var _ref = ref; var prev = _ref.prev; node.next = _ref; node.prev = prev; _ref.prev = node; prev.next = node; this._size++; return node; }; /** * Insert a value after a specific node in the list. * * @param value - The value to insert after the reference node. * * @param ref - The reference node of interest. If this is `null`, * the value will be added to the end of the list. * * @returns The list node which holds the value. * * #### Notes * The reference node must be owned by the list. * * #### Complexity * Constant. */ LinkedList.prototype.insertAfter = function (value, ref) { if (!ref || ref === this._last) { return this.addLast(value); } if (!(ref instanceof Private.LinkedListNode) || ref.list !== this) { throw new Error('Reference node is not owned by the list.'); } var node = new Private.LinkedListNode(this, value); var _ref = ref; var next = _ref.next; node.next = next; node.prev = _ref; _ref.next = node; next.prev = node; this._size++; return node; }; /** * Remove and return the value at the beginning of the list. * * @returns The removed value, or `undefined` if the list is empty. * * #### Complexity * Constant. */ LinkedList.prototype.removeFirst = function () { var node = this._first; if (!node) { return undefined; } if (node === this._last) { this._first = null; this._last = null; } else { this._first = node.next; this._first.prev = null; } node.list = null; node.next = null; node.prev = null; this._size--; return node.value; }; /** * Remove and return the value at the end of the list. * * @returns The removed value, or `undefined` if the list is empty. * * #### Complexity * Constant. */ LinkedList.prototype.removeLast = function () { var node = this._last; if (!node) { return undefined; } if (node === this._first) { this._first = null; this._last = null; } else { this._last = node.prev; this._last.next = null; } node.list = null; node.next = null; node.prev = null; this._size--; return node.value; }; /** * Remove a specific node from the list. * * @param node - The node to remove from the list. * * #### Complexity * Constant. * * #### Notes * The node must be owned by the list. */ LinkedList.prototype.removeNode = function (node) { if (!(node instanceof Private.LinkedListNode) || node.list !== this) { throw new Error('Node is not owned by the list.'); } var _node = node; if (_node === this._first && _node === this._last) { this._first = null; this._last = null; } else if (_node === this._first) { this._first = _node.next; this._first.prev = null; } else if (_node === this._last) { this._last = _node.prev; this._last.next = null; } else { _node.next.prev = _node.prev; _node.prev.next = _node.next; } _node.list = null; _node.next = null; _node.prev = null; this._size--; }; /** * Remove all values from the list. * * #### Complexity * Linear. */ LinkedList.prototype.clear = function () { var node = this._first; while (node) { var next = node.next; node.list = null; node.prev = null; node.next = null; node = next; } this._first = null; this._last = null; this._size = 0; }; return LinkedList; }()); exports.LinkedList = LinkedList; /** * The namespace for the `LinkedList` class statics. */ (function (LinkedList) { /** * Create a linked list from an iterable of values. * * @param values - The iterable or array-like object of interest. * * @returns A new linked list initialized with the given values. * * #### Complexity * Linear. */ function from(values) { var list = new LinkedList(); list.assign(values); return list; } LinkedList.from = from; /** * A forward iterator for values in a linked list. */ var ForwardValueIterator = /** @class */ (function () { /** * Construct a forward value iterator. * * @param node - The first node in the list. */ function ForwardValueIterator(node) { this._node = node; } /** * Get an iterator over the object's values. * * @returns An iterator which yields the object's values. */ ForwardValueIterator.prototype.iter = function () { return this; }; /** * Create an independent clone of the iterator. * * @returns A new independent clone of the iterator. */ ForwardValueIterator.prototype.clone = function () { return new ForwardValueIterator(this._node); }; /** * Get the next value from the iterator. * * @returns The next value from the iterator, or `undefined`. */ ForwardValueIterator.prototype.next = function () { if (!this._node) { return undefined; } var node = this._node; this._node = node.next; return node.value; }; return ForwardValueIterator; }()); LinkedList.ForwardValueIterator = ForwardValueIterator; /** * A reverse iterator for values in a linked list. */ var RetroValueIterator = /** @class */ (function () { /** * Construct a retro value iterator. * * @param node - The last node in the list. */ function RetroValueIterator(node) { this._node = node; } /** * Get an iterator over the object's values. * * @returns An iterator which yields the object's values. */ RetroValueIterator.prototype.iter = function () { return this; }; /** * Create an independent clone of the iterator. * * @returns A new independent clone of the iterator. */ RetroValueIterator.prototype.clone = function () { return new RetroValueIterator(this._node); }; /** * Get the next value from the iterator. * * @returns The next value from the iterator, or `undefined`. */ RetroValueIterator.prototype.next = function () { if (!this._node) { return undefined; } var node = this._node; this._node = node.prev; return node.value; }; return RetroValueIterator; }()); LinkedList.RetroValueIterator = RetroValueIterator; /** * A forward iterator for nodes in a linked list. */ var ForwardNodeIterator = /** @class */ (function () { /** * Construct a forward node iterator. * * @param node - The first node in the list. */ function ForwardNodeIterator(node) { this._node = node; } /** * Get an iterator over the object's values. * * @returns An iterator which yields the object's values. */ ForwardNodeIterator.prototype.iter = function () { return this; }; /** * Create an independent clone of the iterator. * * @returns A new independent clone of the iterator. */ ForwardNodeIterator.prototype.clone = function () { return new ForwardNodeIterator(this._node); }; /** * Get the next value from the iterator. * * @returns The next value from the iterator, or `undefined`. */ ForwardNodeIterator.prototype.next = function () { if (!this._node) { return undefined; } var node = this._node; this._node = node.next; return node; }; return ForwardNodeIterator; }()); LinkedList.ForwardNodeIterator = ForwardNodeIterator; /** * A reverse iterator for nodes in a linked list. */ var RetroNodeIterator = /** @class */ (function () { /** * Construct a retro node iterator. * * @param node - The last node in the list. */ function RetroNodeIterator(node) { this._node = node; } /** * Get an iterator over the object's values. * * @returns An iterator which yields the object's values. */ RetroNodeIterator.prototype.iter = function () { return this; }; /** * Create an independent clone of the iterator. * * @returns A new independent clone of the iterator. */ RetroNodeIterator.prototype.clone = function () { return new RetroNodeIterator(this._node); }; /** * Get the next value from the iterator. * * @returns The next value from the iterator, or `undefined`. */ RetroNodeIterator.prototype.next = function () { if (!this._node) { return undefined; } var node = this._node; this._node = node.prev; return node; }; return RetroNodeIterator; }()); LinkedList.RetroNodeIterator = RetroNodeIterator; })(LinkedList = exports.LinkedList || (exports.LinkedList = {})); exports.LinkedList = LinkedList; /** * The namespace for the module implementation details. */ var Private; (function (Private) { /** * The internal linked list node implementation. */ var LinkedListNode = /** @class */ (function () { /** * Construct a new linked list node. * * @param list - The list which owns the node. * * @param value - The value for the link. */ function LinkedListNode(list, value) { /** * The linked list which created and owns the node. */ this.list = null; /** * The next node in the list. */ this.next = null; /** * The previous node in the list. */ this.prev = null; this.list = list; this.value = value; } return LinkedListNode; }()); Private.LinkedListNode = LinkedListNode; })(Private || (Private = {}));