数据结构:双向链表
目录:
1、简介
在说双向链表之前,肯定要先说一下单向链表,因为双向链表是在单向链表的基础上进行修改。【单链表】
那么我们这里简单的画一个单链表的图:
单链表每个节点都有一个next属性,都指向了下一个节点,这就形成了一个链表的结构,那么这次记录的双向链表,表如其名,我们的单链表只是每个节点只有一个next属性指向其他节点,而我们的双向链表不仅仅有next属性,还有pre属性。
这个图应该还是挺清晰的哈,双向链表在原单向链表的基础上增加了一个pre属性,指向了当前节点的前一个结点。
2、简单使用
1)创建节点
1 /*节点*/ 2 /*英雄类-水浒传*/ 3 class HeroNode2 { 4 5 public int no; 6 public String name; 7 public String nickName; 8 9 public HeroNode2 next; 10 public HeroNode2 pre; 11 12 public HeroNode2() { 13 } 14 15 public HeroNode2(int no, String name, String nickName) { 16 this.no = no; 17 this.name = name; 18 this.nickName = nickName; 19 } 20 21 @Override 22 public String toString() { 23 return "HeroNode2{" + 24 "no=" + no + 25 ", name='" + name + '\'' + 26 ", nickName='" + nickName + '\'' + 27 '}'; 28 } 29 }
节点中no、name、nickName为基础字段,为该节点存储的数据,pre和next分别指向前一个节点和后一个节点
2、创建链表对象
1 /*双向链表*/ 2 class DoubleLinkedList { 3 4 /*头节点*/ 5 private HeroNode2 head = new HeroNode2(); 6 }
创建一个链表对象来存放操作双向链表的方法
3、判断是否为空的方法
如果头节点的next为空,那么就说明该链表中没有数据
/*判断链表是否为空*/ public boolean isEmpty() { return head.next == null; }
4、判断该节点是否已经存在的方法
1 /*判断该节点是否已经存在与链表中*/ 2 public boolean isExits(HeroNode2 heroNode) { 3 if (isEmpty()) { 4 return false; 5 } 6 HeroNode2 tmp = head.next; 7 while (true) { 8 if (tmp == heroNode) { 9 return true; 10 } 11 if (tmp == null) { 12 return false; 13 } 14 tmp = tmp.next; 15 } 16 }
首先判断是否为空,如果为空,那肯定不存在,如果不为空,那么就遍历链表进行判断
5、将节点添加到链表的底部
1 /*将节点添加到链表的底部*/ 2 public boolean addHeroNode(HeroNode2 heroNode) { 3 /*如果为空,那么直接添加到链表的底部*/ 4 if (isEmpty()) { 5 head.next = heroNode; 6 heroNode.pre = head; 7 return true; 8 } 9 /*判断是否已经存在于链表中*/ 10 if (isExits(heroNode)) { 11 System.err.println(heroNode + "已经存在于链表中不能添加"); 12 return false; 13 } 14 HeroNode2 tmp = head.next; 15 while (true) { 16 if (tmp.next == null) { 17 tmp.next = heroNode; 18 heroNode.pre = tmp; 19 return true; 20 } else { 21 tmp = tmp.next; 22 } 23 } 24 }
先判断是否为空,如果为空那么就直接放置到头结点的next中,然后把头结点放置到节点的pre中。
如果不为空,那么就遍历,只要遍历到尾部,例如尾部节点为end,我们需要加进去的节点为node,那么只需要将node赋值给end.next,然后将end赋值给node.pre,那么end的next往后的一条线和node.pre往前的一条线就连成了。
6、将节点添加到链表,保持从小到大的顺序
1 /*将节点添加到链表中,保持从小到大的顺序*/ 2 public boolean addHeroNodeOrder(HeroNode2 heroNode) { 3 /*如果为空,那么直接添加到尾部*/ 4 if (isEmpty()) { 5 head.next = heroNode; 6 heroNode.pre = head; 7 return true; 8 } 9 /*判断该节点是否存在于链表中,如果存在,则不要进行添加*/ 10 /*判断是否已经存在于链表中*/ 11 if (isExits(heroNode)) { 12 System.err.println(heroNode + "已经存在于链表中不能添加"); 13 return false; 14 } 15 /*从第一个元素开始遍历*/ 16 HeroNode2 tmp = head.next; 17 while (true) { 18 if (tmp.no > heroNode.no) { 19 /*如果当前节点的no大于需要添加的节点的no,那么就将需要加入的节点放置到当前节点的前一个*/ 20 tmp.pre.next = heroNode; 21 heroNode.pre = tmp.pre; 22 tmp.pre = heroNode; 23 heroNode.next = tmp; 24 return true; 25 } else if (tmp.next == null) { 26 /*tmp的下一个为空,说明已经完了,直接加到末尾*/ 27 tmp.next = heroNode; 28 heroNode.pre = tmp; 29 return true; 30 } else { 31 tmp = tmp.next; 32 } 33 } 34 }
首先是判断是否为空,如果为空,那么就直接添加到head后。
然后再判断该节点是否已经存在,如果已经存在,那么则不能添加。
然后遍历链表,如果当前当前遍历到的节点为current,然后需要添加的节点为node
如果current的no大于node的no的话,那么我们就需要将node存到current的前面去。
首先让current的pre的next指向node,然后node.pre就等于current.pre,然后至此,current的前一个节点就会指向current,然后我们需要做的就是将current的pre指向我们的node,最后我们需要将node.next指向我们的current。
7、修改节点
1 /*修改节点数据,通过no*/ 2 public boolean update(HeroNode2 heroNode2) { 3 if (isEmpty()) { 4 System.err.println("链表为空!"); 5 return false; 6 } 7 HeroNode2 tmp = head.next; 8 while (tmp != null) { 9 if (tmp.no == heroNode2.no) { 10 tmp.name = heroNode2.name; 11 tmp.nickName = heroNode2.nickName; 12 return true; 13 } else { 14 tmp = tmp.next; 15 } 16 } 17 return false; 18 }
这个没啥逻辑,就是遍历,找到了就修改name和nickName
8、删除节点
1 /*删除节点*/ 2 public boolean delByNo(Integer no) { 3 if (isEmpty()) { 4 System.err.println("当前链表为空,无法删除"); 5 return false; 6 } 7 HeroNode2 tmp = head.next; 8 /*可能有多个相同no的节点,所以当成立删除时并不停止。*/ 9 boolean flag = false; 10 while (tmp != null) { 11 if (tmp.no == no) { 12 /**/ 13 tmp.pre.next = tmp.next; 14 tmp.next.pre = tmp.pre; 15 flag = true; 16 } 17 tmp = tmp.next; 18 } 19 return flag; 20 }
遍历,如果当前节点的no就是我们需要删除的no,假设我们当前节点为current,然后需要删除的no为3
那么就是如果current.no==3的话,那么我们current的pre的next就等于node.next,然后node.next.pre就等于我们current的pre。
9、全部源码
1 package t4; 2 3 4 import t2.Test; 5 6 import java.util.Random; 7 8 /** 9 * @author 自在仙 10 * @create 2020年04月19 12:20 11 */ 12 public class DoubleLinkedListDemo { 13 14 public static void main(String[] args) { 15 DoubleLinkedList doubleLinkedList = new DoubleLinkedList(); 16 HeroNode2 heroNode = new HeroNode2(1, "林冲", "林大哥"); 17 HeroNode2 heroNode2 = new HeroNode2(2, "林冲2", "林大哥"); 18 HeroNode2 heroNode3 = new HeroNode2(3, "林冲3", "林大哥"); 19 HeroNode2 heroNode5 = new HeroNode2(3, "林冲3", "林大哥"); 20 HeroNode2 heroNode4 = new HeroNode2(4, "林冲4", "林大哥"); 21 doubleLinkedList.addHeroNodeOrder(heroNode4); 22 doubleLinkedList.addHeroNodeOrder(heroNode3); 23 doubleLinkedList.addHeroNodeOrder(heroNode5); 24 doubleLinkedList.addHeroNodeOrder(heroNode); 25 doubleLinkedList.addHeroNodeOrder(heroNode2); 26 /* 27 doubleLinkedList.display(); 28 29 doubleLinkedList.delByNo(3); 30 31 System.out.println("-------------");*/ 32 33 doubleLinkedList.display(); 34 35 } 36 } 37 38 /*双向链表*/ 39 class DoubleLinkedList { 40 41 /*头节点*/ 42 private HeroNode2 head = new HeroNode2(); 43 44 /*判断链表是否为空*/ 45 public boolean isEmpty() { 46 return head.next == null; 47 } 48 49 /*将节点添加到链表的底部*/ 50 public boolean addHeroNode(HeroNode2 heroNode) { 51 /*如果为空,那么直接添加到链表的底部*/ 52 if (isEmpty()) { 53 head.next = heroNode; 54 heroNode.pre = head; 55 return true; 56 } 57 /*判断是否已经存在于链表中*/ 58 if (isExits(heroNode)) { 59 System.err.println(heroNode + "已经存在于链表中不能添加"); 60 return false; 61 } 62 HeroNode2 tmp = head.next; 63 while (true) { 64 if (tmp.next == null) { 65 tmp.next = heroNode; 66 heroNode.pre = tmp; 67 return true; 68 } else { 69 tmp = tmp.next; 70 } 71 } 72 } 73 74 /*将节点添加到链表中,保持从小到大的顺序*/ 75 public boolean addHeroNodeOrder(HeroNode2 heroNode) { 76 /*如果为空,那么直接添加到尾部*/ 77 if (isEmpty()) { 78 head.next = heroNode; 79 heroNode.pre = head; 80 return true; 81 } 82 /*判断该节点是否存在于链表中,如果存在,则不要进行添加*/ 83 /*判断是否已经存在于链表中*/ 84 if (isExits(heroNode)) { 85 System.err.println(heroNode + "已经存在于链表中不能添加"); 86 return false; 87 } 88 /*从第一个元素开始遍历*/ 89 HeroNode2 tmp = head.next; 90 while (true) { 91 if (tmp.no > heroNode.no) { 92 /*如果当前节点的no大于需要添加的节点的no,那么就将需要加入的节点放置到当前节点的前一个*/ 93 tmp.pre.next = heroNode; 94 heroNode.pre = tmp.pre; 95 tmp.pre = heroNode; 96 heroNode.next = tmp; 97 return true; 98 } else if (tmp.next == null) { 99 /*tmp的下一个为空,说明已经完了,直接加到末尾*/ 100 tmp.next = heroNode; 101 heroNode.pre = tmp; 102 return true; 103 } else { 104 tmp = tmp.next; 105 } 106 } 107 } 108 109 /*删除节点*/ 110 public boolean delByNo(Integer no) { 111 if (isEmpty()) { 112 System.err.println("当前链表为空,无法删除"); 113 return false; 114 } 115 HeroNode2 tmp = head.next; 116 /*可能有多个相同no的节点,所以当成立删除时并不停止。*/ 117 boolean flag = false; 118 while (tmp != null) { 119 if (tmp.no == no) { 120 /**/ 121 tmp.pre.next = tmp.next; 122 tmp.next.pre = tmp.pre; 123 flag = true; 124 } 125 tmp = tmp.next; 126 } 127 return flag; 128 } 129 130 /*修改节点数据,通过no*/ 131 public boolean update(HeroNode2 heroNode2) { 132 if (isEmpty()) { 133 System.err.println("链表为空!"); 134 return false; 135 } 136 HeroNode2 tmp = head.next; 137 while (tmp != null) { 138 if (tmp.no == heroNode2.no) { 139 tmp.name = heroNode2.name; 140 tmp.nickName = heroNode2.nickName; 141 return true; 142 } else { 143 tmp = tmp.next; 144 } 145 } 146 return false; 147 } 148 149 /*判断该节点是否已经存在与链表中*/ 150 public boolean isExits(HeroNode2 heroNode) { 151 if (isEmpty()) { 152 return false; 153 } 154 HeroNode2 tmp = head.next; 155 while (true) { 156 if (tmp == heroNode) { 157 return true; 158 } 159 if (tmp == null) { 160 return false; 161 } 162 tmp = tmp.next; 163 } 164 } 165 166 /*遍历该链表*/ 167 public void display() { 168 if (isEmpty()) { 169 System.out.println("当前链表为空"); 170 } 171 HeroNode2 temp = head.next; 172 while (temp != null) { 173 System.out.println(temp); 174 temp = temp.next; 175 } 176 } 177 178 } 179 180 /*节点*/ 181 /*英雄类-水浒传*/ 182 class HeroNode2 { 183 184 public int no; 185 public String name; 186 public String nickName; 187 188 public HeroNode2 next; 189 public HeroNode2 pre; 190 191 public HeroNode2() { 192 } 193 194 public HeroNode2(int no, String name, String nickName) { 195 this.no = no; 196 this.name = name; 197 this.nickName = nickName; 198 } 199 200 @Override 201 public String toString() { 202 return "HeroNode2{" + 203 "no=" + no + 204 ", name='" + name + '\'' + 205 ", nickName='" + nickName + '\'' + 206 '}'; 207 } 208 }
如果有说错了的地方,请您联系我,QQ:2366567504,万分抱歉。