DoublyLinkedList.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import defined from './defined.js';
  2. import defineProperties from './defineProperties.js';
  3. /**
  4. * @private
  5. */
  6. function DoublyLinkedList() {
  7. this.head = undefined;
  8. this.tail = undefined;
  9. this._length = 0;
  10. }
  11. defineProperties(DoublyLinkedList.prototype, {
  12. length : {
  13. get : function() {
  14. return this._length;
  15. }
  16. }
  17. });
  18. /**
  19. * @private
  20. */
  21. function DoublyLinkedListNode(item, previous, next) {
  22. this.item = item;
  23. this.previous = previous;
  24. this.next = next;
  25. }
  26. /**
  27. * Adds the item to the end of the list
  28. * @param {*} [item]
  29. * @return {DoublyLinkedListNode}
  30. */
  31. DoublyLinkedList.prototype.add = function(item) {
  32. var node = new DoublyLinkedListNode(item, this.tail, undefined);
  33. if (defined(this.tail)) {
  34. this.tail.next = node;
  35. this.tail = node;
  36. } else {
  37. this.head = node;
  38. this.tail = node;
  39. }
  40. ++this._length;
  41. return node;
  42. };
  43. function remove(list, node) {
  44. if (defined(node.previous) && defined(node.next)) {
  45. node.previous.next = node.next;
  46. node.next.previous = node.previous;
  47. } else if (defined(node.previous)) {
  48. // Remove last node
  49. node.previous.next = undefined;
  50. list.tail = node.previous;
  51. } else if (defined(node.next)) {
  52. // Remove first node
  53. node.next.previous = undefined;
  54. list.head = node.next;
  55. } else {
  56. // Remove last node in the linked list
  57. list.head = undefined;
  58. list.tail = undefined;
  59. }
  60. node.next = undefined;
  61. node.previous = undefined;
  62. }
  63. /**
  64. * Removes the given node from the list
  65. * @param {DoublyLinkedListNode} node
  66. */
  67. DoublyLinkedList.prototype.remove = function(node) {
  68. if (!defined(node)) {
  69. return;
  70. }
  71. remove(this, node);
  72. --this._length;
  73. };
  74. /**
  75. * Moves nextNode after node
  76. * @param {DoublyLinkedListNode} node
  77. * @param {DoublyLinkedListNode} nextNode
  78. */
  79. DoublyLinkedList.prototype.splice = function(node, nextNode) {
  80. if (node === nextNode) {
  81. return;
  82. }
  83. // Remove nextNode, then insert after node
  84. remove(this, nextNode);
  85. var oldNodeNext = node.next;
  86. node.next = nextNode;
  87. // nextNode is the new tail
  88. if (this.tail === node) {
  89. this.tail = nextNode;
  90. } else {
  91. oldNodeNext.previous = nextNode;
  92. }
  93. nextNode.next = oldNodeNext;
  94. nextNode.previous = node;
  95. };
  96. export default DoublyLinkedList;