双向链表

双向链表

区别

  1. 单向链表查找的方向只能是从前往后这一方向,而双向链表可以向前也可以向后查找
  2. 单向链表不能自我删除,只能通过辅助节点,也就是找到待删除节点的前一个节点;而双向链表可以实现自我删除

思路

  1. 创建节点类和双向链表类
    class HeroNode3{
        int no;//节点编号
        String name;//节点名称
        String nickName;//节点昵称
        HeroNode3 next;//节点指向域,指向后一个节点
        HeroNode3 pre;//指向前一个节点
    
        //构造器
        public HeroNode3(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 + "]" + "\n";
        }
    }
    class LinkedList{
        //头节点
        private HeroNode3 head = new HeroNode3(0,"","");
    }
  1. 获取头节点方法
    //获取头节点
        public HeroNode3 getHead(){
            return head;
        }
  1. 添加节点
    思路:
    1. 根据节点编号no进行插入链表,不是直接在链表最后插入节点
    2. 定义一个辅助节点temp指向head
    3. 遍历链表,找到编号比待插入节点大的节点temp.next,此时temp是比待插入节点编号小的节点,让
      heroNode.next = temp.next; ——>插入节点的next指向temp节点的下一个节点
      temp.next = heroNode; ——>让temp节点的next指向插入的节点
      temp.next.pre = heroNode; ——>让temp节点下一个节点的pre指向插入节点
      heroNode.pre = temp; ——>让插入节点的pre指向temp
    //添加数据到链表中
        public void addByOrder(HeroNode3 heroNode){
            //头节点不能动,使用辅助变量temp
            HeroNode3 temp = head;
            boolean flag = false;//记录是否有需要存入的节点编号和链表中已有编号一样
            while(true){
                if (temp.next == null){
                    break;
                }
                //遍历找到所插节点的位置
                //比如temp的id为2,temp.next的id为5,则将所需存入的节点插到temp后面,temp.next前面
                if (temp.next.no > heroNode.no){
                    break;
                }else if (temp.next.no == heroNode.no){
                    flag = true;//说明该节点编号在链表中已存在,无法插入
                    break;
                }
                temp = temp.next;//后移一位进行遍历
            }
            //存在相同编号,无法插入节点
            if (flag == true){
                System.out.println("该节点编号" + heroNode.no + "在链表中已存在,无法插入数据");
            }else{
                //找到所需位置,进行插入
                heroNode.next = temp.next;
                temp.next = heroNode;
                temp.next.pre = heroNode;
                heroNode.pre = temp;
            }
        }
  1. 显示链表,遍历(跟单链表的遍历一样,只是双链表可以向前查找)
    //查节点,遍历所有
        public void list(){
            if (head.next == null){
                System.out.println("链表为空!");
                return;
            }
            HeroNode3 temp = head.next;
            while(true){
                if (temp == null){
                    break;
                }
                System.out.println(temp);
                temp = temp.next;
            }
        }
  1. 修改节点(跟单链表的修改一样,只是修改链表的部分结构,多加一个pre指向域)
    //根据编号no修改节点信息
        public void update(HeroNode3 heroNode){
            if (head.next == null){
                System.out.println("链表为空!!!");
                return;
            }
            HeroNode3 temp = head.next;
            boolean flag = false;//记录是否找到特定节点
            while(true){
                if (temp == null){//链表遍历完
                    break;
                }
                if (temp.no == heroNode.no){//找到要修改的节点
                    flag = true;
                    break;
                }
                temp = temp.next;//temp后移进行遍历
            }
            if (flag){//找到了,重新设置信息
                temp.name = heroNode.name;
                temp.nickName = heroNode.nickName;
            }else{
                System.out.println(heroNode.no + "节点在链表中找不到!!!");
            }
        }
  1. 删除节点
    思路:
    1. 定义一个辅助节点temp,到链表中遍历
    2. 找到待删除节点,让temp指向它,此时temp即是待删除节点
    3. 进行删除节点temp,分两种情况:一种是该待删除节点是链表最后一个节点;另一种是该节点不是链表最后一个节点
    4. 针对第一种情况要进行判断,判断temp.next若为空,则不需要执行temp.next.pre = temp.pre;这一语句
    5. 若temp.next == null,则需执行temp.next.pre = temp.pre;这一语句
    //删除指定节点
        public void delete(int no){
            if (head.next == null){
                System.out.println("链表为空!!!");
                return;
            }
            HeroNode3 temp = head.next;
            boolean flag = false;//记录是否找到要删除的节点
            while(true) {
                if (temp == null) {//链表遍历结束
                    break;
                }
                if (temp.no == no){//找到要删除的节点,让flag=true
                    flag = true;
                    break;
                }
                temp = temp.next;//temp后移进行遍历
            }
            if (flag){//找到了,删除节点
                temp.pre.next = temp.next;
                //待删除的节点下一个节点不为空(不进行判断直接执行下面的语句,若待删除节点是最后一个,会出现空指针异常)
                if (temp.next != null) {
                    temp.next.pre = temp.pre;
                }
            }else{
                System.out.println(no + "节点在链表中不存在!!!");
            }
        }

完整代码

    package LinkedList;
    
    /**
     * Created by lenovo on 2021/3/15.
     */
    public class DoubleLinkedList {
        public static void main(String[] args) {
            HeroNode3 hero1 = new HeroNode3(1, "宋江", "及时雨");
            HeroNode3 hero2 = new HeroNode3(2, "卢俊义", "玉麒麟");
            HeroNode3 hero3 = new HeroNode3(3, "吴用", "智多星");
            HeroNode3 hero4 = new HeroNode3(4, "林冲", "豹子头");
            HeroNode3 hero5 = new HeroNode3(5, "武松", "行者");
    
            LinkedList linkedList = new LinkedList();
            //添加节点
            linkedList.addByOrder(hero1);
            linkedList.addByOrder(hero2);
            linkedList.addByOrder(hero4);
            linkedList.addByOrder(hero5);
            linkedList.addByOrder(hero3);
    
            linkedList.list();
    
            //修改节点
            HeroNode3 newheroNode = new HeroNode3(2, "小卢卢", "玉麒麟啦");
    
            linkedList.update(newheroNode);
            System.out.println("修改后的链表为:");
            linkedList.list();
    
            //删除节点
            linkedList.delete(5);
            System.out.println("删除后的链表为:");
            linkedList.list();
        }
    }
    
    class LinkedList{
        //头节点
        private HeroNode3 head = new HeroNode3(0,"","");
    
        //获取头节点
        public HeroNode3 getHead(){
            return head;
        }
    
        //删除指定节点
        public void delete(int no){
            if (head.next == null){
                System.out.println("链表为空!!!");
                return;
            }
            HeroNode3 temp = head.next;
            boolean flag = false;//记录是否找到要删除的节点
            while(true) {
                if (temp == null) {//链表遍历结束
                    break;
                }
                if (temp.no == no){//找到要删除的节点,让flag=true
                    flag = true;
                    break;
                }
                temp = temp.next;//temp后移进行遍历
            }
            if (flag){//找到了,删除节点
                temp.pre.next = temp.next;
                //待删除的节点下一个节点不为空(不进行判断直接执行下面的语句,若待删除节点是最后一个,会出现空指针异常)
                if (temp.next != null) {
                    temp.next.pre = temp.pre;
                }
            }else{
                System.out.println(no + "节点在链表中不存在!!!");
            }
        }
    
        //根据编号no修改节点信息
        public void update(HeroNode3 heroNode){
            if (head.next == null){
                System.out.println("链表为空!!!");
                return;
            }
            HeroNode3 temp = head.next;
            boolean flag = false;//记录是否找到特定节点
            while(true){
                if (temp == null){//链表遍历完
                    break;
                }
                if (temp.no == heroNode.no){//找到要修改的节点
                    flag = true;
                    break;
                }
                temp = temp.next;//temp后移进行遍历
            }
            if (flag){//找到了,重新设置信息
                temp.name = heroNode.name;
                temp.nickName = heroNode.nickName;
            }else{
                System.out.println(heroNode.no + "节点在链表中找不到!!!");
            }
        }
    
        //添加数据到链表中
        public void addByOrder(HeroNode3 heroNode){
            //头节点不能动,使用辅助变量temp
            HeroNode3 temp = head;
            boolean flag = false;//记录是否有需要存入的节点编号和链表中已有编号一样
            while(true){
                if (temp.next == null){
                    break;
                }
                //遍历找到所插节点的位置
                //比如temp的id为2,temp.next的id为5,则将所需存入的节点插到temp后面,temp.next前面
                if (temp.next.no > heroNode.no){
                    break;
                }else if (temp.next.no == heroNode.no){
                    flag = true;//说明该节点编号在链表中已存在,无法插入
                    break;
                }
                temp = temp.next;//后移一位进行遍历
            }
            //存在相同编号,无法插入节点
            if (flag == true){
                System.out.println("该节点编号" + heroNode.no + "在链表中已存在,无法插入数据");
            }else{
                //找到所需位置,进行插入
                heroNode.next = temp.next;
                temp.next = heroNode;
                temp.next.pre = heroNode;
                heroNode.pre = temp;
            }
        }
    
        //查节点,遍历所有
        public void list(){
            if (head.next == null){
                System.out.println("链表为空!");
                return;
            }
            HeroNode3 temp = head.next;
            while(true){
                if (temp == null){
                    break;
                }
                System.out.println(temp);
                temp = temp.next;
            }
        }
    }
    
    class HeroNode3{
        int no;//节点编号
        String name;//节点名称
        String nickName;//节点昵称
        HeroNode3 next;//节点指向域,指向后一个节点
        HeroNode3 pre;//指向前一个节点
    
        //构造器
        public HeroNode3(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 + "]" + "\n";
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值