当前位置:   article > 正文

数据结构与算法学习笔记——数据结构(三):双向链表_表中,我们有一个数据域,还有一个指针域,数据域用来存储相关数据,而指针域则负责链

表中,我们有一个数据域,还有一个指针域,数据域用来存储相关数据,而指针域则负责链

1、介绍

单链表中,有一个数据域,还有一个指针域,数据域用来存储相关数据,而指针域则负责链表之间的“联系”。 而在双向链表中,我们需要有两个指针域,一个负责向后连接,一个负责向前连接。

单向链表的缺点分析: 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。 单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找到 temp,temp 是待删除节点的前一个节点

2、思路分析

双向链表的遍历,添加,修改,删除的操作思路:

1)遍历和单链表一样,只是可以向前,也可以向后查找

2)添加 (默认添加到双向链表的最后) 先找到双向链表的最后这个节点 temp.next = newHeroNode newHeroNode.pre = temp;

3)修改思路和原来的单向链表一样.

4)删除因为是双向链表,因此,我们可以实现自我删除某个节点 直接找到要删除的这个节点,比如 temp;删除操作temp.pre.next = temp.next;temp.next.pre = temp.pre;

3、代码实现

  1. package com.czq.datastructure;
  2. /**
  3. * 双向链表
  4. *
  5. * @author czq
  6. * @date 2020/08/17
  7. */
  8. public class DoubleLinkedList {
  9. //先初始化一个头节点,头节点不要动,不存放具体的数据
  10. private HeroNode2 head = new HeroNode2(0, "", "");
  11. //返回头节点
  12. public HeroNode2 getHead() {
  13. return head;
  14. }
  15. // 添加一个节点到双向链表的最后
  16. public void add(HeroNode2 heroNode) {
  17. // 因为 head 节点不能动,因此需要一个辅助遍历 temp
  18. HeroNode2 temp = head;
  19. //遍历链表,找到最后
  20. while (temp.next != null) {
  21. // 如果没有找到最后, 将 temp 后移
  22. temp = temp.next;
  23. }
  24. //当退出 while 循环时,temp 就指向了链表的最后,将最后这个节点的 next 指向新的节点,并将这个节点的 pre 指向 temp
  25. temp.next = heroNode;
  26. heroNode.pre = temp;
  27. }
  28. //添加一个节点到双向链表,要考虑编号顺序,根据编号将节点插入到指定位置
  29. //1. 找到当前链表的最后节点,2. 判断是否有这个编号节点,3.将这个节点的插入到找到的这个位置
  30. public void addByOrder(HeroNode2 heroNode) {
  31. //辅助变量 temp
  32. HeroNode2 temp = head;
  33. // flag 标志添加的编号是否存在
  34. boolean flag = false;
  35. while (temp.next != null) {
  36. //位置找到,就在 temp 的后面插入
  37. if (temp.next.no > heroNode.no) {
  38. break;
  39. } else if (temp.next.no == heroNode.no) {
  40. //说明需要添加的 heroNode 的编号已然存在
  41. flag = true;
  42. break;
  43. }
  44. //后移,遍历当前链表
  45. temp = temp.next;
  46. }
  47. //判断 flag 的值,编号是否存在
  48. if (flag) {
  49. System.out.printf("准备插入的英雄的编号 %d 已经存在了, 不能加入\n", heroNode.no);
  50. } else {
  51. //插入到链表中, temp 的后面
  52. // 将新节点的 next 指向 temp 的 next 节点
  53. heroNode.next = temp.next;
  54. //将新节点的 pre 指向temp
  55. heroNode.pre = temp;
  56. //将 temp 原先的 next 节点的 pre 指向新节点
  57. temp.next.pre = heroNode;
  58. //将 temp 的下一个节点指向新节点
  59. temp.next = heroNode;
  60. }
  61. }
  62. //删除一个节点,
  63. // 1.对于双向链表,直接找到要删除的这个节点 2.找到后,自我删除即可
  64. public void del(int no) {
  65. if (head.next == null) {
  66. System.out.println("链表为空,无法删除");
  67. return;
  68. }
  69. //辅助变量 temp
  70. HeroNode2 temp = head.next;
  71. // 标志是否找到待删除节点的
  72. boolean flag = false;
  73. while (temp != null) {
  74. //找到的待删除节点 temp
  75. if (temp.no == no) {
  76. flag = true;
  77. break;
  78. }
  79. //temp 后移,遍历
  80. temp = temp.next;
  81. }
  82. //判断 flag,是否找到需要删除的节点
  83. if (flag) {
  84. //删除节点
  85. temp.pre.next = temp.next;
  86. //如果是最后一个节点,就不需要执行下面这句话,否则出现空指针
  87. if (temp.next != null) {
  88. temp.next.pre = temp.pre;
  89. }
  90. } else {
  91. System.out.printf("要删除的 %d 节点不存在\n", no);
  92. }
  93. }
  94. //修改一个节点的内容,双向链表的节点内容修改和单向链表一样
  95. public void update(HeroNode2 newHeroNode) {
  96. if (head.next == null) {
  97. System.out.println("链表为空");
  98. return;
  99. }
  100. //辅助变量 temp
  101. HeroNode2 temp = head.next;
  102. //表示是否找到该节点
  103. boolean flag = false;
  104. while (temp != null) {
  105. //找到对应no的节点
  106. if (temp.no == newHeroNode.no) {
  107. flag = true;
  108. break;
  109. }
  110. //temp 后移,遍历
  111. temp = temp.next;
  112. }
  113. //根据 flag 判断是否找到要修改的节点
  114. if (flag) {
  115. temp.name = newHeroNode.name;
  116. temp.nickname = newHeroNode.nickname;
  117. } else {
  118. // 没有找到
  119. System.out.printf("没有找到 编号 %d 的节点,不能修改\n", newHeroNode.no);
  120. }
  121. }
  122. //遍历双向链表,显示链表
  123. public void list() {
  124. //判断链表是否为空
  125. if (head.next == null) {
  126. System.out.println("链表为空");
  127. return;
  128. }
  129. // 因为头节点,不能动,因此需要一个辅助变量来遍历
  130. HeroNode2 temp = head.next;
  131. while (temp != null) {
  132. // 输出节点的信息
  133. System.out.println(temp);
  134. // 将 temp 后移
  135. temp = temp.next;
  136. }
  137. }
  138. }
  139. // 定义 HeroNode2,每个 HeroNode2 对象就是一个节点
  140. class HeroNode2 {
  141. public int no;
  142. public String name;
  143. public String nickname;
  144. public HeroNode2 next; // 指向下一个节点, 默认为 null
  145. public HeroNode2 pre; // 指向前一个节点, 默认为 null
  146. public HeroNode2(int no, String name, String nickname) {
  147. this.no = no;
  148. this.name = name;
  149. this.nickname = nickname;
  150. }
  151. @Override
  152. public String toString() {
  153. return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
  154. }
  155. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/448968
推荐阅读
相关标签
  

闽ICP备14008679号