单向链表的缺点分析
- 查找的方向只能是一个方向,而双向链表可以向前或者向后查找;
- 单向链表不能自我删除,需要靠辅助节点,单链表删除节点时,总是找到temp节点(待删除节点的前一个节点)辅助操作;
双向链表操作分析

双向链表的遍历和修改与单链表一样,只是遍历时可以向前也可以向后;
- 添加(添加到最后)
- 先找到双向链表的最后这个节点 temp
- temp.next = newHeroNode; newHeroNode.pre = temp;
- 删除
- 找到要删除的这个节点 temp
- temp.pre.next = temp.next; temp.next.pre = temp.pre;
双链表操作实现
1. 节点定义
package com.zsy.datastructure.linkedlist.doublelinklist;/** * 以水浒英雄信息作为双向链表的节点 * * @author zhangshuaiyin */public class HeroNode { int no; String name; String nickName; // next: 指向下一个节点,默认为null HeroNode next; // pre: 指向前一个节点,默认为null HeroNode pre; public HeroNode(int no, String name, String nickName) { this.no = no; this.name = name; this.nickName = nickName; } @Override public String toString() { return "HeroNode{" + "no=" + no + ", name='" + name + '\'' + ", nickName='" + nickName + '\'' + '}'; }}
2. 双向链表操作方法
package com.zsy.datastructure.linkedlist.doublelinklist;/** * 单链表存储水浒英雄节点信息 * * @author zhangshuaiyin */public class DoubleLinkedList { /** * head 节点,指向链表第一个节点,定位链表地址 */ private final HeroNode head = new HeroNode(0, "", ""); /** * @param node 添加节点:从链表最后 */ public void add(HeroNode node) { HeroNode temp = head; while (temp.next != null) { temp = temp.next; } temp.next = node; node.pre = temp; } /** * 按照编号由小到大的顺序插入节点,编号不可重复 * * @param node 插入节点 */ public void addByOrder(HeroNode node) { HeroNode temp = head; while (temp.next != null) { if (temp.next.no == node.no) { System.out.printf("编号 %d 已存在,插入失败\n", node.no); return; } else if (temp.next.no > node.no) { // 此时说明新节点应该插入 temp 的下一个位置 break; } temp = temp.next; } //退出时代表temp已到达需要插入的节点的位置的 //插入节点的下一个节点为temp的下一个节点 node.next = temp.next; // temp.next = null 说明插入的是第一个节点 if (temp.next != null) { // 设置插入位置的上一个节点 temp.next.pre = node; } //将temp的下一个节点更改为新插入的节点 temp.next = node; //设置插入节点的上一个节点 node.pre = temp; } /** * 根据新节点信息修改链表中相同编号的节点 * * @param node 新节点 */ public void update(HeroNode node) { HeroNode temp = head.next; while (temp != null) { if (temp.no == node.no) { temp.name = node.name; temp.nickName = node.nickName; return; } temp = temp.next; } System.out.printf("没有找到编号是 %d 的节点,不能修改\n", node.no); } /** * @param no 根据编号 no 删除链表中对应的节点 */ public void delete(int no) { HeroNode temp = head.next; while (temp != null) { if (temp.no == no) { temp.pre.next = temp.next; if (temp.next != null) { temp.next.pre = temp.pre; } return; } temp = temp.next; } System.out.printf("没有找到编号是 %d 的节点,不能修改\n", no); } /** * 打印链表信息 */ public void list() { if (head.next == null) { throw new RuntimeException("当前链表为空"); } HeroNode temp = head.next; while (temp != null) { System.out.println(temp); temp = temp.next; } }}
3. 测试方法
package com.zsy.datastructure.linkedlist.doublelinklist;/** * @author zhangshuaiyin * @date 2021-04-06 14:33 */public class DoubleLinkedListTest { static HeroNode hero1 = new HeroNode(1, "宋江", "及时雨"); static HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟"); static HeroNode hero3 = new HeroNode(3, "吴用", "智多星"); static HeroNode hero4 = new HeroNode(4, "公孙胜", "入云龙"); static DoubleLinkedList linkedList = new DoubleLinkedList(); public static void main(String[] args) { System.out.println("-----------------从链表最后添加节点:---------------------"); testAdd(); linkedList = new DoubleLinkedList(); System.out.println("-----------------按节点编号大小添加:---------------------"); testAddByOrder(); System.out.println("-----------------按节点编号修改节点:---------------------"); HeroNode newNode = new HeroNode(2, "Lu JunYi", "Yu QiLin"); testUpdate(newNode); System.out.println("-----------------按节点编号删除节点:---------------------"); testDelete(); } /** */ private static void testDelete() { linkedList.delete(4); linkedList.list(); } /** * @param newNode 更新节点 */ private static void testUpdate(HeroNode newNode) { linkedList.update(newNode); linkedList.list(); } /** * 测试按编号大小添加元素 */ private static void testAddByOrder() { linkedList.addByOrder(hero1); linkedList.addByOrder(hero4); linkedList.addByOrder(hero2); linkedList.addByOrder(hero3); linkedList.list(); } /** * add() 方法按照添加顺序从最后添加 */ public static void testAdd() { linkedList.add(hero1); linkedList.add(hero4); linkedList.add(hero2); linkedList.add(hero3); linkedList.list(); }}