管理單向鏈表的缺點分析:
- 單向鏈表,查找的方向只能是一個方向,而雙向鏈表可以向前或者向后查找。
- 單向鏈表不能自我刪除,需要靠輔助節點 ,而雙向鏈表,則可以自我刪除,所以前面我們單鏈表刪除節點時,總是找到 temp,temp 是待刪除節點的前一個節點。
雙向鏈表如何完成遍歷,添加,修改和刪除的思路
1) 遍歷 :和單鏈表一樣,只是可以向前,也可以向后查找
2) 添加 (默認添加到雙向鏈表的最后)
(1)先找到雙向鏈表的最后這個節點
(2) temp.next = newNode;
(3) newNode.pre = temp;
3) 修改 思路和原來的單向鏈表一樣
4) 刪除
(1) 因為是雙向鏈表,因此,我們可以實現自我刪除某個節點
(2) 直接找到要刪除的這個節點,比如 temp
temp.pre.next = temp.next;
temp.next.pre = temp.pre;//若刪除的是最后一個節點,會有空指針異常
代碼實現
1. class doublelinkedlist { 2. //先初始化一個頭節點,頭節點不能動,不存放具體數據 3. private hero head = new hero(-1, "", ""); 4. 5. //添加節點 6. public void add(hero h) { 7. //因為head節點不能動,因此我們需要一個輔助變量temp 8. hero temp = head; 9. //遍歷鏈表,找到最后一個節點 10. while (true) { 11. if (temp.getNext() == null) { 12. break; 13. } 14. //如果沒有到最后,將temp后移 15. temp = temp.getNext(); 16. } 17. //當退出while循環時,temp就指向了鏈表的最后 18. //將鏈表的最后一個節點的next指向要添加的這個節點 19. //將要添加的這個節點的pre指向鏈表的最后一個節點 20. temp.setNext(h); 21. h.setPre(temp); 22. } 23. 24. //第二種方式在添加英雄時,根據排名將英雄插入到指定位置 25. //(如果有這個排名,則添加失敗,並給出提示) 26. public void addByOrder(hero h) { 27. //因為頭節點不能動,因此我們仍然通過一個輔助指針(變量)來幫助找到添加的位置 28. hero temp = head; 29. boolean flag = false;// flag 標志添加的編號是否存在,默認為 false 30. while (true) { 31. if (temp.getNext() == null) {//說明 temp 已經在鏈表的最后 32. break; 33. } else if (temp.getNext().getNum() > h.getNum()) {//位置找到,就在 temp 的后面插入 34. break; 35. } else if (temp.getNext().getNum() == h.getNum()) {//說明希望添加的 heroNode 的編號已然存在 36. flag = true; 37. break; 38. } 39. temp = temp.getNext();//后移,遍歷當前鏈表 40. } 41. if (flag) { //不能添加,說明編號存在 42. System.out.println("添加的序號為" + h.getNum() + "的英雄序號已經存在,添加失敗。"); 43. return; 44. } 45. 46. //插入到鏈表中, temp 的后面 47. // (注意,先連兩個節點之間的pre和next,再連另外兩個節點的pre和next,否則會出錯!!) 48. if (temp.getNext() != null) temp.getNext().setPre(h); 49. h.setNext(temp.getNext());//將h與temp的下一個節點相連(pre和next指針) 50. 51. h.setPre(temp); 52. temp.setNext(h);//再將h與temp節點相連(pre和next指針) 53. } 54. 55. //顯示鏈表(遍歷) 56. public void show() { 57. //判斷鏈表是否為空 58. if (head.getNext() == null) { 59. System.out.println("show():鏈表為空。。。。"); 60. return; 61. } 62. //因為頭節點,不能動,因此我們需要一個輔助變量來遍歷 63. hero temp = head.getNext(); 64. while (true) { 65. //判斷是否到鏈表最后 66. if (temp == null) { 67. break; 68. } 69. //輸出節點的信息 70. System.out.println(temp.toString()); 71. //將 temp 后移, 一定小心 72. temp = temp.getNext(); 73. } 74. } 75. 76. //修改節點的信息, 根據 no 編號來修改,即 no 編號不能改. 77. //說明 78. //1. 根據 newHeroNode 的 no 來修改即可 79. public void update(hero h) { 80. hero temp = head.getNext();//定義一個輔助變量 81. boolean flag = false;//表示是否找到該節點 82. //判斷鏈表是否空 83. if (head.getNext() == null) { 84. System.out.println("update():鏈表為空。。。。"); 85. return; 86. } 87. //找到需要修改的節點, 根據 num值 88. while (true) { 89. if (temp == null) { 90. break;//已經遍歷完鏈表 91. } 92. if (temp.getNum() == h.getNum()) { 93. flag = true; 94. break; 95. } 96. temp = temp.getNext(); 97. } 98. if (flag) { 99. temp.setName(h.getName()); 100. temp.setNikname(h.getNikname()); 101. } else {//沒有找到 102. System.out.printf("沒有找到 編號 %d 的節點,不能修改\n", h.getNum()); 103. } 104. } 105. 106. //刪除節點 107. //思路 108. //1. head 不能動,因此我們需要一個 temp 輔助節點找到待刪除節點的前一個節點 109. //2. 雙向鏈表中我們在比較時,是 temp.no 和需要刪除的節點的 no 比較 110. public void delete(int n) { 111. if (head.getNext() == null) { 112. System.out.println("delete():鏈表為空。。。。"); 113. return; 114. } 115. hero temp = head.getNext();// 輔助變量(指針) 116. boolean flag = false;// 標志是否找到待刪除節點的 117. while (true) { 118. if (temp == null) {//已經到鏈表的最后 119. break; 120. } 121. if (temp.getNum() == n) {//找到的待刪除節點 temp 122. flag = true; 123. break; 124. } 125. temp = temp.getNext();//temp 后移,遍歷 126. } 127. if (flag) { 128. temp.getPre().setNext(temp.getNext()); 129. if (temp.getNext() != null) { 130. temp.getNext().setPre(temp.getPre()); 131. } 132. } else { 133. System.out.printf("沒有找到 編號 %d 的節點,不能刪除\n", n); 134. } 135. } 136. }