5、链表-双向链表
来源:https://www.bilibili.com/video/BV1B4411H76f?p=24
一、介绍
相比单链表来说
1、双向链表可以向前和向后查找,而单链表只能查找一个方向;
2、双向链表可以自我删除,单链表只能通过辅助结点,即需要找到要删除的结点前面的那个结点。
二、双向链表思路
2.1、增加结点
1、添加到链表尾部
新建一个结点类,结点类中除了单链表中已经有的属性,还要添加一个属性(pre)指向前一个结点。
找到最后一个结点,需要注意的是,前后都要兼顾
2、按照位置添加
依然需要找到要添加位置的前一个结点temp
后面
【newNode.next = temp.next】
【temp.next.pre = newNode】
前面
【temp.next = newNode】
【newNode.pre = temp】
2.2、修改结点
与单链表相似
2.3、删除结点
找到要删除的结点temp
【temp.pre.next】=【temp.next】
【temp.next.pre】=【temp.pre】
三、实现
结点
1 public class Node2 { 2 public int no;//编号 3 public String name;//名字 4 public String nickName;//昵称 5 public Node2 next; 6 public Node2 pre; 7 8 public Node2(int no, String name, String nickName) { 9 this.no = no; 10 this.name = name; 11 this.nickName = nickName; 12 } 13 14 @Override 15 public String toString() { 16 return "Node2{" + 17 "no=" + no + 18 ", name='" + name + '\'' + 19 ", nickName='" + nickName + '\'' + 20 '}'; 21 } 22 }
双向链表
1 public class DoubleLinkedList { 2 private Node2 head = new Node2(0,"",""); 3 4 //向链表尾部添加新结点 5 public void addNode(Node2 newNode){ 6 Node2 temp = head; 7 while (true){ 8 if(temp.next == null){ 9 break; 10 } 11 temp = temp.next; 12 } 13 temp.next = newNode; 14 newNode.pre = temp; 15 } 16 17 //按照位置添加新结点(当前按照编号no从小到大) 18 public void addByOrder(Node2 newNode){ 19 Node2 temp = head; 20 //避免出现相同的no 21 boolean flag = false; 22 while (true){ 23 if(temp.next == null){ 24 break; 25 } 26 if(temp.next.no > newNode.no){ 27 break; 28 } 29 if(temp.next.no == newNode.no){ 30 flag = true; 31 break; 32 } 33 temp = temp.next; 34 } 35 if(flag){ 36 System.out.printf("编号%d已经存在",newNode.no); 37 System.out.println(); 38 }else { 39 if(temp.next != null){ 40 newNode.next = temp.next; 41 temp.next.pre = newNode; 42 } 43 temp.next = newNode; 44 newNode.pre = temp; 45 } 46 } 47 48 //修改结点 49 public void update(Node2 newNode){ 50 if(head.next == null){ 51 System.out.println("链表为空,无法修改"); 52 return; 53 } 54 Node2 temp = head.next; 55 boolean flag = false;//默认找不到对应的结点 56 while(true){ 57 if(temp == null){ 58 break; 59 } 60 if(temp.no == newNode.no){ 61 flag = true; 62 break; 63 } 64 temp = temp.next; 65 } 66 if(flag){ 67 temp.name = newNode.name; 68 temp.nickName = newNode.nickName; 69 }else { 70 System.out.printf("没有找到编号为%d的结点",newNode.no); 71 System.out.println(); 72 } 73 } 74 75 //删除结点 76 public void delete(int no){ 77 if(head.next == null){ 78 System.out.println("链表为空,无法删除"); 79 return; 80 } 81 boolean flag = false;//默认找不到这个结点 82 Node2 temp = head.next; 83 while (true){ 84 if(temp == null){ 85 break; 86 } 87 if(temp.no == no){ 88 flag = true; 89 break; 90 } 91 temp = temp.next; 92 } 93 94 if(flag){ 95 temp.next.pre = temp.pre; 96 temp.pre.next = temp.next; 97 }else { 98 System.out.printf("没有找到编号为%d的结点",no); 99 System.out.println(); 100 } 101 } 102 103 public void show(){ 104 if(head.next == null){ 105 System.out.println("链表为空,无法展示"); 106 return; 107 } 108 Node2 temp = head.next; 109 while (temp != null){ 110 System.out.println(temp); 111 temp = temp.next; 112 } 113 } 114 }
它的测试与单链表相似,这里就不再添加测试代码了。