• 06-双向链表


    1. 思路分析

    • 遍历:遍历和单链表一样,但可以有 2 个方向:往前和往后
    • 添加(默认添加到链尾)
      • 通过遍历先找到当前双向链表的尾结点
      • temp.next = newNode;
      • newNode.pre = temp;
    • 修改:原理与单链表相同
    • 删除
      • 因为是双向链表,故可直接找到 [待删除结点],实现自我删除
      • temp.pre.next = temp.next;
      • temp.next.pre = temp.pre;

    2. 代码实现

    public class DoubleLinkedList {
        // 先初始化 [头结点], 头结点不存放数据
        private HeroNode2 head = new HeroNode2(0,"","");
    
        public HeroNode2 getHead() {
            return head;
        }
    
        // 添加结点到双向链表(追加)
        public void add(HeroNode2 node) {
            // 1. 找到 [尾结点]
            // 1.1 定义一个临时变量, 用来指向链表当前遍历到的元素
            HeroNode2 temp = head;
            // 1.2 遍历:当退出while循环时, temp此时指向的是尾结点
            while (temp.next != null) temp = temp.next;
            // 2. 追加(注意是双向链表)
            temp.next = node;
            node.pre = temp;
        }
    
        // 按编号顺序将结点到链表(如果有这个排名, 则添加失败, 并给出提示)
        public void insertByOrder(HeroNode2 node) {
            // 1. 找到新结点要插入的位置(遍历 + 辅助变量)
            HeroNode2 temp = head;
            // 用来标识新结点的编号是否已存在
            boolean flag = false;
            // 循环终止时, temp指向链表尾结点
            while (temp.next != null) {
                // temp指向新结点要放置位置的前一个结点
                if (temp.next.no > node.no) { // find it!
                    break;
                } else if (temp.next.no == node.no) { // 说明编号已存在
                    flag = true;
                    break;
                }
                temp = temp.next; // 后移
            }
    
            // 2. 新结点应插入到 temp 和 temp.next 之间
            if (!flag) {
                node.next = temp.next;
                node.pre = temp;
                temp.next = node;
            } else { // 不能加入, 编号已存在
                System.out.printf("编号%d已存在, 不能插入
    ", node.no);
            }
        }
    
    
        // 根据编号修改结点数据
        public void updateByNo(HeroNode2 node) {
            // 1. 判断链表是否空
            if (head.next == null)
                System.out.println("链表为空");
            // 2. 找到需要修改的结点
            HeroNode2 temp = head.next;
            // 3. 标识是否找到该结点
            boolean flag = false;
            while (temp != null) {
                if (temp.no == node.no) {
                    flag = true;
                    break;
                }
                temp = temp.next;
            }
            // 根据 flag 是否找到要修改的结点
            if (flag) {
                temp.name = node.name;
                temp.nickname = node.nickname;
            } else {
                System.out.printf("不存在编号为%d的结点
    ", node.no);
            }
        }
    
        // 删除结点(自我删除)
        public void deleteNode(int no) {
            // 1. 判断链表是否空
            if (head.next == null) {
                System.out.println("链表为空");
                return;
            }
            // 2. 对于双向链表, 直接找到待删除结点即可
            HeroNode2 temp = head.next;
            boolean flag = false;
            while (temp != null) {
                if (temp.no == no) {
                    flag = true;
                    break;
                }
                temp = temp.next;
            }
            if (flag) {
                // 3. 待删除结点因没有任何引用指向, 故会被垃圾回收机制回收
                temp.pre.next = temp.next;
                // 4. 如果删除的是尾结点就不需要执行下面这句(否则会报空指针异常)
                if(temp.next != null) temp.next.pre = temp.pre;
            } else {
                System.out.printf("不存在编号为%d的结点
    ", no);
            }
        }
    
        // 打印链表(遍历)
        public void showList() {
            if (head.next == null) {
                System.out.println("链表为空");
                return;
            }
    
            // 头结点不能动, 故需要一个临时变量来遍历
            HeroNode2 temp = head.next;
            while (temp != null) {
                System.out.println(temp);
                temp = temp.next;
            }
        }
    }
    
    class HeroNode2 {
        public int no;
        public String name;
        public String nickname;
        public HeroNode2 next;
        public HeroNode2 pre;
    
        public HeroNode2(int no, String name, String nickname) {
            super();
            this.no = no;
            this.name = name;
            this.nickname = nickname;
        }
    
        @Override
        public String toString() {
            return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
        }
    }
    
  • 相关阅读:
    Java web 会话技术 cookie与session
    Spring bean的bean的三种实例化方式
    Spring基础篇——通过Java注解和XML配置装配bean(转载)
    Spring的核心api和两种实例化方式
    Spring 7种事务传播类型
    leetcode 697
    leetcode 387
    Spring_002 依赖注入方式实现
    Spring_第一个Spring入门案例IOC
    谈谈对Spring IOC的理解(转载)
  • 原文地址:https://www.cnblogs.com/liujiaqi1101/p/12214985.html
Copyright © 2020-2023  润新知