双向链表和普通链表的区别在于,在链表中,一个节点只有链向下一个节点的链接,而在双向链表中,链接是双向的:一个链向下一个元素, 另一个链向前一个元素
与单向链表相比,双向链表有新增两点

  • 节点新增 prev 指针
  • 链表增加 tail 标记(类比head)

    实现一个双向链表

    1. function DoublyLinkedList() {
    2. let Node = function(element){
    3. this.element = element;
    4. this.next = null;
    5. this.prev = null; //NEW
    6. };
    7. let length = 0;
    8. let head = null;
    9. let tail = null; //NEW
    10. this.append = function(element){
    11. let node = new Node(element),
    12. current;
    13. if (head === null){ //first node on list
    14. head = node;
    15. tail = node; //NEW
    16. } else {
    17. //attach to the tail node //NEW
    18. tail.next = node;
    19. node.prev = tail;
    20. tail = node;
    21. }
    22. length++; //update size of list
    23. };
    24. this.insert = function(position, element){
    25. //check for out-of-bounds values
    26. if (position >= 0 && position <= length){
    27. let node = new Node(element),
    28. current = head,
    29. previous,
    30. index = 0;
    31. if (position === 0){ //add on first position
    32. if (!head){ //NEW
    33. head = node;
    34. tail = node;
    35. } else {
    36. node.next = current;
    37. current.prev = node; //NEW {1}
    38. head = node;
    39. }
    40. } else if (position === length) { //last item //NEW
    41. current = tail; // {2}
    42. current.next = node;
    43. node.prev = current;
    44. tail = node;
    45. } else {
    46. while (index++ < position){ //{3}
    47. previous = current;
    48. current = current.next;
    49. }
    50. node.next = current;
    51. previous.next = node;
    52. current.prev = node; //NEW
    53. node.prev = previous; //NEW
    54. }
    55. length++; //update size of list
    56. return true;
    57. } else {
    58. return false;
    59. }
    60. };
    61. this.removeAt = function(position){
    62. //check for out-of-bounds values
    63. if (position > -1 && position < length){
    64. let current = head,
    65. previous,
    66. index = 0;
    67. //removing first item
    68. if (position === 0){
    69. head = current.next; // {1}
    70. //if there is only one item, then we update tail as well //NEW
    71. if (length === 1){ // {2}
    72. tail = null;
    73. } else {
    74. head.prev = null; // {3}
    75. }
    76. } else if (position === length-1){ //last item //NEW
    77. current = tail; // {4}
    78. tail = current.prev;
    79. tail.next = null;
    80. } else {
    81. while (index++ < position){ // {5}
    82. previous = current;
    83. current = current.next;
    84. }
    85. //link previous with current's next - skip it to remove
    86. previous.next = current.next; // {6}
    87. current.next.prev = previous; //NEW
    88. }
    89. length--;
    90. return current.element;
    91. } else {
    92. return null;
    93. }
    94. };
    95. this.remove = function(element){
    96. let index = this.indexOf(element);
    97. return this.removeAt(index);
    98. };
    99. this.indexOf = function(element){
    100. let current = head,
    101. index = -1;
    102. //check first item
    103. if (element == current.element){
    104. return 0;
    105. }
    106. index++;
    107. //check in the middle of the list
    108. while(current.next){
    109. if (element == current.element){
    110. return index;
    111. }
    112. current = current.next;
    113. index++;
    114. }
    115. //check last item
    116. if (element == current.element){
    117. return index;
    118. }
    119. return -1;
    120. };
    121. this.isEmpty = function() {
    122. return length === 0;
    123. };
    124. this. size = function() {
    125. return length;
    126. };
    127. this.toString = function(){
    128. let current = head,
    129. s = current ? current.element : '';
    130. while(current && current.next){
    131. current = current.next;
    132. s += ', ' + current.element;
    133. }
    134. return s;
    135. };
    136. this.inverseToString = function() {
    137. let current = tail,
    138. s = current ? current.element : '';
    139. while(current && current.prev){
    140. current = current.prev;
    141. s += ', ' + current.element;
    142. }
    143. return s;
    144. };
    145. this.print = function(){
    146. console.log(this.toString());
    147. };
    148. this.printInverse = function(){
    149. console.log(this.inverseToString());
    150. };
    151. this.getHead = function(){
    152. return head;
    153. };
    154. this.getTail = function(){
    155. return tail;
    156. }
    157. }