当前位置:   article > 正文

数据结构——双向链表(双向连接的图解、双向链表的创建、操作双向链表)

双向链表

目录

一、双向链表

二、双向连接的图解:

三、双向链表的创建

四、操作双向链表


一、双向链表

- 单向链表:

  - 只能从头遍历到尾或者从尾遍历到头(一般从头到尾)
  - 也就是链表相连的过程是单向的. 实现的原理是上一个链表中有一个指向下一个的引用.
  - 单向链表有一个比较明显的缺点: 
    - 我们可以轻松的到达下一个节点, 但是回到前一个节点是很难的. 但是, 在实际开发中, 经常会遇到需要回到上一个节点的情况
    - 举个例子: 假设一个文本编辑用链表来存储文本. 每一行用一个String对象存储在链表的一个节点中. 当编辑器用户向下移动光标时, 链表直接操作到下一个节点即可. 但是当用于将光标向上移动呢? 这个时候为了回到上一个节点, 我们可能需要从first开始, 依次走到想要的节点上.

- 双向链表

  - 既可以从头遍历到尾, 又可以从尾遍历到头
  - 也就是链表相连的过程是双向的. 那么它的实现原理, 你能猜到吗?
  - 一个节点既有向前连接的引用, 也有一个向后连接的引用.
  - 双向链表可以有效的解决单向链表中提到的问题.
  - 双向链表有什么缺点呢? 
    - 每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 也就是实现起来要困难一些
    - 并且相当于单向链表, 必然占用内存空间更大一些.
    - 但是这些缺点和我们使用起来的方便程度相比, 是微不足道的.

 

二、双向连接的图解:

 

三、双向链表的创建

  1. // 创建双向链表的构造函数
  2. function DoublyLinkedList() {
  3. // 创建节点构造函数
  4. function Node(element) {
  5. this.element = element
  6. this.next = null
  7. this.prev = null // 新添加的
  8. }
  9. // 定义属性
  10. this.length = 0
  11. this.head = null
  12. this.tail = null // 新添加的
  13. // 定义相关操作方法
  14. }

- 基本思路和单向链表比较相似, 都是创建节点结构函数以及定义一些属性和方法.
- 只是Node中添加了一个this.prev属性, 该属性用于指向上一个节点.
- 另外属性中添加了一个this.tail属性, 该属性指向末尾的节点

四、操作双向链表

1、尾部追加数据

2、正向反向遍历

3、任意位置插入

4、位置移除数据

5、获取元素位置

6、根据元素删除

7、判断是否为空

 8、获取链表长度

9、获取第一个元素

10、获取最后一个元素

  1. class Dnode {
  2. constructor(data) {
  3. this.prev = null;
  4. this.data = data;
  5. this.next = null;
  6. }
  7. }
  8. class DoubleLinkList {
  9. constructor() {
  10. this.head = null;
  11. this.tail = null;
  12. this.len = 0
  13. }
  14. // 1.尾部添加节点
  15. append(ele) {
  16. let newnode = new Dnode(ele);
  17. // console.log(newnode);
  18. if (this.len == 0) { //空链表
  19. this.head = newnode;
  20. this.tail = newnode;
  21. } else {
  22. newnode.prev = this.tail; //新节点.prev = 尾节点
  23. this.tail.next = newnode; //尾节点.next指向新节点
  24. this.tail = newnode; //将尾节点指向新节点
  25. }
  26. this.len++;
  27. }
  28. // 2.向指定位置插入元素
  29. insert(position, ele) {
  30. // 位置是否合法
  31. if (position < 0 || position > this.len || !Number.isInteger(position)) {
  32. return false
  33. }
  34. let newnode = new Dnode(ele);
  35. if (position == 0) {
  36. if (this.len == 0) { //空链表
  37. this.head = newnode;
  38. this.tail = newnode;
  39. } else {
  40. newnode.next = this.head; //新节点.next指向头节点
  41. this.head.prev = newnode; //头节点.prev指向新节点
  42. this.head = newnode; //头节点指向新节点
  43. }
  44. this.len++
  45. } else if (position == this.len) {
  46. this.append(ele)
  47. } else {
  48. let current = this.head,
  49. index = 0;
  50. while (index < position - 1) {
  51. current = current.next;
  52. index++;
  53. }
  54. // 1.将新节点练上去
  55. newnode.prev = current;
  56. newnode.next = current.next;
  57. // 2.
  58. current.next = newnode;
  59. newnode.next.prev = newnode;
  60. this.len++;
  61. }
  62. }
  63. // 3.移除指定位置的元素
  64. removeAt(position) {
  65. // 位置是否合法
  66. if (position < 0 || position > this.len - 1 || !Number.isInteger(position)) {
  67. return false
  68. }
  69. if (this.len == 0) { //空链表
  70. return
  71. } else {
  72. if (position == 0) {
  73. if (this.len == 1) {
  74. this.head = null;
  75. this.tail = null;
  76. } else {
  77. this.head = this.head.next;
  78. this.head.prev = null;
  79. }
  80. } else if (position == this.len - 1) {
  81. this.tail = this.tail.prev;
  82. this.tail.next = null;
  83. } else {
  84. let current = this.head,
  85. index = 0;
  86. while (index < position - 1) {
  87. current = current.next;
  88. index++
  89. }
  90. current.next = current.next.next;
  91. current.next.prev = current
  92. }
  93. this.len--
  94. }
  95. }
  96. // 4.查找指定元素的位置
  97. indexOf(ele) {
  98. let current = this.head,
  99. index = 0;
  100. while (index < this.len) {
  101. if (current.data == ele) {
  102. return index
  103. } else {
  104. current = current.next;
  105. index++;
  106. }
  107. }
  108. return -1
  109. }
  110. // 5.移除指定元素
  111. remove(ele) {
  112. let index = this.indexOf(ele)
  113. this.removeAt(index)
  114. }
  115. // 6.正向遍历
  116. toAfterString() {
  117. let current = this.head,
  118. index = 0,
  119. res = "";
  120. while (index < this.len) {
  121. res += "-" + current.data;
  122. current = current.next;
  123. index++;
  124. }
  125. return res.slice(1)
  126. }
  127. // 7.反向遍历
  128. toBeforeString() {
  129. let current = this.tail,
  130. index = this.len - 1,
  131. res = "";
  132. while (index >= 0) {
  133. res += "-" + current.data;
  134. current = current.prev;
  135. index--;
  136. }
  137. return res.slice(1)
  138. }
  139. }
  140. let dlist = new DoubleLinkList();
  141. for (let i = 0; i < 9; i++) {
  142. dlist.append(i)
  143. }
  144. dlist.remove(6)
  145. console.log(dlist.toAfterString());
  146. console.log(dlist.toBeforeString());
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号