当前位置:   article > 正文

7-无头双向非循环链表_非循环双向链表

非循环双向链表

目录

1.定义

2.代码

2.1.车厢类

2.2.火车类

2.2.1.在链表的头部添加节点

2.2.2.在链表的尾部添加节点

2.2.3.在链表的任意位置index处添加节点

2.2.4.查询链表的任意位置index处的节点值

2.2.5.修改链表中任意位置index处的节点值

2.2.6.传入一个双向链表节点,将该节点从双向链表中删除

2.2.7.删除链表中第一次出现某个值的节点

2.2.8.删除链表中值为val的所有节点

2.2.9.判断链表的index是否合法

2.2.10.根据index与size的大小关系快速定位指定index位置的节点

2.2.11.toString()方法

2.3.总代码实现


1.定义

既要存储下一个节点地址,还要存储前一个节点地址。是Java的集合框架中LinkedList底层实现。

2.代码

2.1.车厢类

  1. /**
  2. * 车厢类
  3. */
  4. class DoubleNode{
  5. //指向前驱节点
  6. DoubleNode prev;
  7. //存储的具体元素
  8. int val;
  9. //指向后继节点
  10. DoubleNode next;
  11. //有参构造
  12. public DoubleNode(int val){
  13. this.val=val;
  14. }
  15. }

2.2.火车类

  1. /**
  2. * 火车类 基于int的双向链表
  3. */
  4. public class DoubleLinkedList {
  5. //存储的具体车厢个数
  6. private int size;
  7. //头节点
  8. private DoubleNode first;
  9. //尾节点
  10. private DoubleNode last;
  11. //具体方法实现
  12. //...
  13. }

2.2.1.在链表的头部添加节点

  1. /**
  2. * 头插
  3. * @param val
  4. */
  5. public void addFirst(int val) {
  6. //引入一个局部变量,暂时存储一下头节点的地址
  7. DoubleNode f = first;
  8. //要插入一个节点,首先要new一个节点
  9. DoubleNode node = new DoubleNode(val);
  10. first = node; //因为是头插,那么这行代码不管当前链表是否为空都会执行
  11. if(f == null) { //若链表为空,则新建的节点既是头节点又是尾节点
  12. last = node;
  13. } else {
  14. node.next = f;
  15. f.prev = node;
  16. }
  17. size++;
  18. }

2.2.2.在链表的尾部添加节点

  1. /**
  2. * 尾插
  3. * @param val
  4. */
  5. public void addLast(int val) {
  6. //引入一个局部变量,暂时存储一下尾节点的地址
  7. DoubleNode l = last;
  8. DoubleNode node = new DoubleNode(val);
  9. last = node;
  10. if(l == null) {
  11. first = node;
  12. } else {
  13. node.prev = l;
  14. l.next = node;
  15. }
  16. size++;
  17. }

2.2.3.在链表的任意位置index处添加节点

  1. /**
  2. * 任意index处添加元素
  3. * @param val
  4. */
  5. public void addIndex(int index, int val) {
  6. if(index < 0 || index > size) {
  7. System.err.println("add index illegal!");
  8. return;
  9. } else if(index == 0) {
  10. addFirst(val);
  11. } else if(index == size) {
  12. addLast(val);
  13. } else {
  14. //此时0 < index < size
  15. //在报错方法(未写)上使用快捷键Alt+Enter,自动生成指定方法
  16. DoubleNode node = node(index);
  17. //指向当前位置的前驱节点
  18. DoubleNode prev = node.prev;
  19. //要插入的新节点
  20. DoubleNode newNode = new DoubleNode(val);
  21. //先处理后半部分引用链
  22. newNode.next = node; ①
  23. node.prev = newNode; ②
  24. //再处理前半部分引用链
  25. prev.next = newNode; ③
  26. newNode.prev = prev; ④
  27. size++;
  28. }
  29. }

2.2.4.查询链表的任意位置index处的节点值

  1. /**
  2. * 根据index索引取得节点值
  3. * @param index
  4. * @return
  5. */
  6. public int get(int index) {
  7. if(rangeCheck(index)) {
  8. DoubleNode node = node(index);
  9. return node.val;
  10. } else {
  11. System.out.println("get index illegal!");
  12. return -1;
  13. }
  14. }

2.2.5.修改链表中任意位置index处的节点值

  1. /**
  2. * 修改index处的值为newVal
  3. * @param index
  4. * @param newVal
  5. */
  6. public void set(int index, int newVal) {
  7. if(rangeCheck(index)) {
  8. DoubleNode node = node(index);
  9. node.val = newVal;
  10. } else {
  11. System.out.println("set index illegal!");
  12. }
  13. }

2.2.6.传入一个双向链表节点,将该节点从双向链表中删除

  1. /**
  2. * 传入一个双向链表节点,将该节点从双向链表中删除
  3. * 核心思想 分治,先处理前驱或后继,再处理另一半的情况
  4. * @param node
  5. */
  6. private void unlinkNode(DoubleNode node) {
  7. //待删除节点的前驱
  8. DoubleNode prev = node.prev;
  9. //待删除结点的后继
  10. DoubleNode next = node.next;
  11. //先处理前半部分引用链
  12. //判断边界
  13. if(prev == null) {
  14. //说明此时待删除的节点恰好是头节点
  15. first = next;
  16. } else {
  17. //此时前驱节点不为空
  18. prev.next = next;
  19. node.prev = null;
  20. }
  21. //再处理后半部分引用链
  22. if(next == null) {
  23. last = prev;
  24. } else {
  25. //此时后继节点不为空
  26. next.prev = prev;
  27. node.next = null;
  28. }
  29. size--;
  30. }

2.2.7.删除链表中第一次出现某个值的节点

  1. /**
  2. * 删除第一次出现值为val的元素
  3. * @param val
  4. */
  5. public void removeValueOnce(int val) {
  6. //只需要从头开始遍历
  7. for (DoubleNode x = first; x != null; x = x.next) {
  8. if(x.val == val) {
  9. unlinkNode(x);
  10. return;
  11. }
  12. }
  13. }

2.2.8.删除链表中值为val的所有节点

  1. /**
  2. * 删除单链表中所有值为val的节点
  3. * @param val
  4. */
  5. public void removeAllValue(int val) {
  6. for(DoubleNode x = first; x != null;) {
  7. if(x.val == val){
  8. //x就是待删除的元素
  9. //先暂存一下next的节点地址
  10. DoubleNode next = x.next;
  11. unlinkNode(x);
  12. x = next; //真正让x走向next
  13. } else {
  14. x = x.next;
  15. }
  16. }
  17. }

2.2.9.判断链表的index是否合法

  1. /**
  2. * 判断链表的index是否合法
  3. * @param index
  4. * @return
  5. */
  6. private boolean rangeCheck(int index) {
  7. if(index < 0 || index >= size) {
  8. return false;
  9. }
  10. return true;
  11. }

2.2.10.根据index与size的大小关系快速定位指定index位置的节点

  1. /**
  2. * 根据index与size的大小关系快速定位指定index位置的节点
  3. * @param index
  4. * @return
  5. */
  6. private DoubleNode node(int index) {
  7. if(index < size >> 1) {
  8. //从头向后
  9. DoubleNode node = first;
  10. for (int i = 0; i < index; i++) {
  11. node = node.next;
  12. }
  13. return node;
  14. } else {
  15. //从后向前
  16. DoubleNode node = last;
  17. for (int i = size-1; i > index; i--) {
  18. node = node.prev;
  19. }
  20. return node;
  21. }
  22. }

2.2.11.toString()方法

  1. public String toString() {
  2. String ret = "";
  3. DoubleNode node = first;
  4. while(node != null) {
  5. ret += node.val + "->";
  6. node = node.next;
  7. }
  8. ret += "NULL";
  9. return ret;
  10. }

2.3.总代码实现

  1. /**
  2. * 车厢类
  3. */
  4. class DoubleNode{
  5. //指向前驱节点
  6. DoubleNode prev;
  7. //存储的具体元素
  8. int val;
  9. //指向后继节点
  10. DoubleNode next;
  11. //有参构造
  12. public DoubleNode(int val){
  13. this.val=val;
  14. }
  15. }
  16. /**
  17. * 火车类 基于int的双向链表
  18. */
  19. public class DoubleLinkedList {
  20. //存储的具体车厢个数
  21. private int size;
  22. //头节点
  23. private DoubleNode first;
  24. //尾节点
  25. private DoubleNode last;
  26. /**
  27. * 头插
  28. * @param val
  29. */
  30. public void addFirst(int val){
  31. //引入一个局部变量,暂时存储一下头节点的地址
  32. DoubleNode f=first;
  33. //要插入一个节点,首先要new一个节点
  34. DoubleNode node=new DoubleNode(val);
  35. first=node;
  36. if(f==null){
  37. last=node;
  38. }else{
  39. node.next=f;
  40. f.prev=node;
  41. }
  42. size++;
  43. }
  44. /**
  45. * 尾插
  46. * @param val
  47. */
  48. public void addLast(int val) {
  49. //引入一个局部变量,暂时存储一下尾节点的地址
  50. DoubleNode l = last;
  51. DoubleNode node = new DoubleNode(val);
  52. last = node;
  53. if(l == null) {
  54. first = node;
  55. } else {
  56. node.prev = l;
  57. l.next = node;
  58. }
  59. size++;
  60. }
  61. /**
  62. * 任意index处添加元素
  63. * @param val
  64. */
  65. public void addIndex(int index, int val) {
  66. if(index < 0 || index > size) {
  67. System.err.println("add index illegal!");
  68. return;
  69. } else if(index == 0) {
  70. addFirst(val);
  71. } else if(index == size) {
  72. addLast(val);
  73. } else {
  74. //此时0 < index < size
  75. //在报错方法(未写)上使用快捷键Alt+Enter,自动生成指定方法
  76. DoubleNode node = node(index);
  77. //指向当前位置的前驱节点
  78. DoubleNode prev = node.prev;
  79. //要插入的新节点
  80. DoubleNode newNode = new DoubleNode(val);
  81. //先处理后半部分引用链
  82. newNode.next = node;
  83. node.prev = newNode;
  84. //再处理前半部分引用链
  85. prev.next = newNode;
  86. newNode.prev = prev;
  87. size++;
  88. }
  89. }
  90. /**
  91. * 根据index索引取得节点值
  92. * @param index
  93. * @return
  94. */
  95. public int get(int index) {
  96. if(rangeCheck(index)) {
  97. DoubleNode node = node(index);
  98. return node.val;
  99. } else {
  100. System.out.println("get index illegal!");
  101. return -1;
  102. }
  103. }
  104. /**
  105. * 修改index处的值为newVal
  106. * @param index
  107. * @param newVal
  108. */
  109. public void set(int index, int newVal) {
  110. if(rangeCheck(index)) {
  111. DoubleNode node = node(index);
  112. node.val = newVal;
  113. } else {
  114. System.out.println("set index illegal!");
  115. }
  116. }
  117. /**
  118. * 传入一个双向链表节点,将该节点从双向链表中删除
  119. * 核心思想 分治,先处理前驱或后继,再处理另一半的情况
  120. * @param node
  121. */
  122. private void unlinkNode(DoubleNode node) {
  123. //待删除节点的前驱
  124. DoubleNode prev = node.prev;
  125. //待删除结点的后继
  126. DoubleNode next = node.next;
  127. //先处理前半部分引用链
  128. //判断边界
  129. if(prev == null) {
  130. //说明此时待删除的节点恰好是头节点
  131. first = next;
  132. } else {
  133. //此时前驱节点不为空
  134. prev.next = next;
  135. node.prev = null;
  136. }
  137. //再处理后半部分引用链
  138. if(next == null) {
  139. last = prev;
  140. } else {
  141. //此时后继节点不为空
  142. next.prev = prev;
  143. node.next = null;
  144. }
  145. size--;
  146. }
  147. /**
  148. * 删除第一次出现值为val的元素
  149. * @param val
  150. */
  151. public void removeValueOnce(int val) {
  152. //只需要从头开始遍历
  153. for (DoubleNode x = first; x != null; x = x.next) {
  154. if(x.val == val) {
  155. unlinkNode(x);
  156. return;
  157. }
  158. }
  159. }
  160. /**
  161. * 删除单链表中所有值为val的节点
  162. * @param val
  163. */
  164. public void removeAllValue(int val){
  165. for(DoubleNode x=first;x!=null;){
  166. if(x.val==val){
  167. //x就是待删除的元素
  168. //先暂存一下next的节点地址
  169. DoubleNode next=x.next;
  170. unlinkNode(x);
  171. x=next;
  172. }else{
  173. x=x.next;
  174. }
  175. }
  176. }
  177. /**
  178. * 根据index与size的大小关系快速定位指定index位置的节点
  179. * @param index
  180. * @return
  181. */
  182. private DoubleNode node(int index) {
  183. if(index < size >> 1) {
  184. //从头向后
  185. DoubleNode node = first;
  186. for (int i = 0; i < index; i++) {
  187. node = node.next;
  188. }
  189. return node;
  190. } else {
  191. //从后向前
  192. DoubleNode node = last;
  193. for (int i = size-1; i > index; i--) {
  194. node = node.prev;
  195. }
  196. return node;
  197. }
  198. }
  199. /**
  200. * 判断链表的index是否合法
  201. * @param index
  202. * @return
  203. */
  204. private boolean rangeCheck(int index) {
  205. if(index < 0 || index >= size) {
  206. return false;
  207. }
  208. return true;
  209. }
  210. public String toString() {
  211. String ret = "";
  212. DoubleNode node = first;
  213. while(node != null) {
  214. ret += node.val + "->";
  215. node = node.next;
  216. }
  217. ret += "NULL";
  218. return ret;
  219. }
  220. public static void main(String[] args) {
  221. DoubleLinkedList doubleLinkedList=new DoubleLinkedList();
  222. doubleLinkedList.addFirst(1);
  223. doubleLinkedList.addFirst(2);
  224. doubleLinkedList.addFirst(3);
  225. doubleLinkedList.addLast(3);
  226. doubleLinkedList.addLast(3);
  227. doubleLinkedList.addLast(3);
  228. //3->2->1->3->3->3->NULL
  229. doubleLinkedList.addIndex(1,99);
  230. //3->99->2->1->3->3->3->NULL
  231. doubleLinkedList.removeValueOnce(99);
  232. //3->2->1->3->3->3->NULL
  233. doubleLinkedList.removeAllValue(3);
  234. //2->1->NULL
  235. System.out.println(doubleLinkedList);
  236. }
  237. }

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

闽ICP备14008679号