数据结构-双向链表
数据结构-双向链表
为什么要有双向链表?
单向链表的缺点分析:
1) 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
2) 单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除 时节点,总是找到 temp,temp 是待删除节点的前一个节点(认真体会).
分析 双向链表的遍历,添加,修改,删除的操作思路===》代码实现
1) 遍历 方和 单链表一样,只是可以向前,也可以向后查找
2) 添加 (默认添加到双向链表的最后)
(1) 先找到双向链表的最后这个节点
(2)temp.next=newHeroNode
(3)newHeroNode.pre=temp;
3) 修改 思路和 原来的单向链表一样.
4) 删除
(1) 因为是双向链表,因此,我们可以实现自我删除某个节点
(2) 直接找到要删除的这个节点,比如 temp
(3) temp.pre.next=temp.next
(4)temp.next.pre=temp.pre; //这里需要判断temp.next != null
添加节点
(1)直接添加到链尾
(2)按照顺序插入
删除节点
源码
package com.orz.LinkList; /** * @author orz * @create 2020-10-24 22:11 */ public class DoubleLinkedListTest { public static void main(String[] args) { DoubleLinkedList link=new DoubleLinkedList(); HeroSingleNode node1=new HeroSingleNode(1,"宋江","及时雨"); HeroSingleNode node2=new HeroSingleNode(2,"吴用","智多星"); HeroSingleNode node3=new HeroSingleNode(3,"林冲","豹子头"); HeroSingleNode node4=new HeroSingleNode(4,"李逵","黑旋风"); DoubleLinkedList link2=new DoubleLinkedList(); //不按顺序添加测试 link2.add(node4); link2.add(node2); link2.add(node1); link2.add(node3); System.out.println("直接添加到链尾"); DoubleLinkedList.showHeroLink(link2); System.out.println("-------------------------------------------------------"); //按顺序添加测试 link.addHeroNodeOrderById(node3); link.addHeroNodeOrderById(node2); link.addHeroNodeOrderById(node1); link.addHeroNodeOrderById(node4); System.out.println("按顺序添加"); DoubleLinkedList.showHeroLink(link); System.out.println("-------------------------------------------------------"); HeroSingleNode newnode4=new HeroSingleNode(4,"李xx","黑xx"); link.updateHeroNode(newnode4); System.out.println("修改节点信息"); DoubleLinkedList.showHeroLink(link); System.out.println("-------------------------------------------------------"); link.deleteHeroNodeById(1); System.out.println("删除节点1"); DoubleLinkedList.showHeroLink(link); System.out.println("-------------------------------------------------------"); } } class DoubleLinkedList{ private HeroSingleNode head=new HeroSingleNode(0,null,null); public HeroSingleNode getHead() { return head; } //遍历双向链表,跟单链表一样 public static void showHeroLink(DoubleLinkedList link) { if (link.head.next == null) { System.out.println("链表为空!!!"); return; } HeroSingleNode temp = link.head.next; while (temp != null) { System.out.println(temp); temp = temp.next; } } //添加节点 //第一种,默认添加到链尾 public void add(HeroSingleNode node) { //因为head不能动,所以需要一个辅助节点变量 HeroSingleNode temp = head; //标记待添加的节点是否已经存在 boolean flag = false; //遍历链表,找到最后 while (true) { //如果节点的next为空说明该节点就是最后一个节点 if (temp.next == null) { break; } if (temp.next.id == node.id) { flag = true; break; } //否则指针下移 temp = temp.next; } if (flag) { System.out.println("添加失败,需要添加id为"+node.id+"的节点已经存在了!!!"); return; } //加入新节点,双向建立联系 temp.next = node; node.pre=temp; } /** * 添加节点信息,第二种:根据排名将英雄插入到指定位置,按照id从小到大排序 */ public void addHeroNodeOrderById(HeroSingleNode node) { //如果还没有任何一个节点,直接插入到head后面 if (head.next == null) { //建立双向联系 head.next = node; node.pre=head; return; } //因为头节点不能动,所以我们仍然通过一个辅助指针(变量)来帮助找到添加的位置 HeroSingleNode temp = head; //标记待添加的节点是否已经存在 boolean flag = false; while (true) { //说明 temp 已经在链表的最后一个了 if (temp.next == null) { break; } //节点已经存在 if (temp.next.id == node.id) { flag = true; break; } //位置找到,就在 temp 的后面插入 if (temp.next.id > node.id) { break; } temp = temp.next; } if (flag) { System.out.println("添加失败,需要添加id为" + node.id + "的节点已经存在了!!!"); } else { //插入的节点与temp的下一个节点建立联系 if (temp.next != null) { temp.next.pre=node; } node.next=temp.next; //插入的节点与temp建立联系 node.pre=temp; temp.next=node; } } /** * 修改链表节点数据,id不要动,跟单链表一样 */ public void updateHeroNode(HeroSingleNode node) { if(head.next==null) { System.out.println("链表为空"); return; } HeroSingleNode temp=head.next; boolean flag=false; while (true) { if(temp==null) { break; } if(temp.id==node.id) { flag=true; break; } temp=temp.next; } if (flag) { temp.heroName=node.heroName; temp.nikeName=node.nikeName; } else { System.out.println("id为"+node.id+"的节点不存在!!!"); } } /** * 删除节点 * //1.head 不能动,因此我们需要一个 temp 辅助节点找到待删除节点的 * //2. 说明我们在比较时,是 temp.id 和 需要删除的节点的 id 比较 */ public void deleteHeroNodeById(int id) { if(head.next==null) { System.out.println("链表为空"); return; } HeroSingleNode temp=head.next; // 标志是否找到待删除节点的 boolean flag=false; while (true) { //已经到了链表最后一个的next if(temp==null) { break; } if(temp.id==id) { flag=true; break; } temp=temp.next; } if(flag) { //temp的前一个节点和后一个节点建立联系 temp.pre.next=temp.next; //这里可能有问题,如果删除最后一个节点 if (temp.next!=null) { temp.next.pre=temp.pre; } } else { System.out.println("链表中没有id为"+id+"的节点数据"); } } } class HeroSingleNode{ public int id; //英雄名 public String heroName; //英雄昵称 public String nikeName; //next域 public HeroSingleNode next; //指向前一个节点 public HeroSingleNode pre; public HeroSingleNode() { } public HeroSingleNode(int id, String heroName, String nikeName) { this.id = id; this.heroName = heroName; this.nikeName = nikeName; } @Override public String toString() { return "HeroSingleNode{" + "id=" + id + ", heroName='" + heroName + '\'' + ", nikeName='" + nikeName + '\'' + '}'; } }