Java数据结构:双向链表Double Linked List基础笔记

单双向链表对比

  • 数据结构异同
    双向链表和单链表相比,其ListNode节点的数据结构当中多了一个变量是节点类型的pre变量,pre用来指向当前节点的前一个节点。

  • 查找方向
    单链表只能向后查找,双向链表可以向后向前查找。

  • 操作思路的异同

    • 遍历:思路基本相同,但双向链表可以向前,也可以向后;
    • 添加:默认添加到双向链表的最后;先找到最后一个节点,同时修改最后一个节点的next域和新节点的pre域。
    • 修改:思路相同
    • 删除:因为是双向链表,可以向前追踪上一个节点,因此可以实现节点的自我删除;直接找到要删除的节点,分别修改其前一个节点的next域,和后一个节点的pre域。
      注意,如果待删除节点是最后一个节点,要考虑其next域为空的问题。
    • 根据排名添加:这个同样要注意节点next域为空的问题。

双向链表代码实现

package ds.sq.linkedlist;

public class DoubleLinkedListDemo {
    public static void main(String[] args){
        dHeroNode hero1=new dHeroNode(1,"宋江","及时雨");
        dHeroNode hero2=new dHeroNode(2,"卢俊义","玉麒麟");
        dHeroNode hero3=new dHeroNode(3,"吴用","智多星");
        dHeroNode hero4=new dHeroNode(4,"林冲","豹子头");
        DoubleLinkedList doubleLinkedList=new DoubleLinkedList();

        //【显示list】
        System.out.println("【测试1】初始化链表为空时:");
        doubleLinkedList.list();
        //1.测试:【根据排名添加addByOrder】添加顺序1、3、2、4
        doubleLinkedList.addByOrder(hero1);
        doubleLinkedList.addByOrder(hero3);
        doubleLinkedList.addByOrder(hero2);
        doubleLinkedList.addByOrder(hero4);
        System.out.println("【测试2】根据排名添加:");
        doubleLinkedList.list();
        //2.测试:【修改】
        System.out.println("【测试3】修改:");
        dHeroNode mHero1=new dHeroNode(1,"Song Jiang","Ji Shiyu");
        doubleLinkedList.modify(mHero1);
        doubleLinkedList.list();
        //3.测试:【删除】
        System.out.println("【测试4】删除:");
        doubleLinkedList.del(5);
        doubleLinkedList.list();
    }
}

class dHeroNode{
    public int no;
    public String name;
    public String nickname;
    public dHeroNode next;
    public dHeroNode pre;
    public dHeroNode(int hno,String hname,String hnickname){
        this.no=hno;
        this.name=hname;
        this.nickname=hnickname;
    }

    public String toString(){
        return "dHeroNode [no"+no+"]name["+name+"]nickname["+nickname+"]";
    }
}

class DoubleLinkedList{
    private dHeroNode head=new dHeroNode(0,"","");

    public void add(dHeroNode dheroNode){
        //因为head节点不能动 因此我们需要一个辅助变量
        dHeroNode tHeroNode=head;
        while(true){
            if(tHeroNode.next==null){
                tHeroNode.next=dheroNode;
                dheroNode.pre=tHeroNode;
                break;
            }
            // 如果没有找到就将t后移
            tHeroNode=tHeroNode.next;
        }
    }

    //考虑编号的顺序时
    public void addByOrder(dHeroNode dheroNode){
        //因为头结点不能动,我们仍然通过一个辅助指针,帮助找到添加的位置
        //找的temp位于添加位置的前一个结点,否则加入不了
        dHeroNode tHeroNode=head;
        boolean flag=false;
        while(true){
            if(tHeroNode.next==null){//说明链表已经到最后
                break;
            }
            if( tHeroNode.next.no>dheroNode.no){
                break;
            }else if(tHeroNode.next.no==dheroNode.no){
                flag=true;
                break;
            }
            tHeroNode=tHeroNode.next;//后移
        }
        if(flag==true){
            //不可以添加
            System.out.printf("准备插入的英雄的编号 %d 已经存在\n",dheroNode.no);
        }else{
            dheroNode.next=tHeroNode.next;
            if(tHeroNode.next!=null){tHeroNode.next.pre=dheroNode;}
            tHeroNode.next=dheroNode;
            dheroNode.pre=tHeroNode;
        }
    }

    public void list(){
        if(head.next==null){
            System.out.println("链表为空");
            return;
        }
        dHeroNode tHeroNode=head.next;   //这里直接指向第一个有编号的节点,避免程序输出头结点;
        while(true){
            //是否到链表最后
            if(tHeroNode==null){
                break;
            }
            //输出节点信息
            System.out.println(tHeroNode);
            tHeroNode=tHeroNode.next;
        }
    }

    public void modify(dHeroNode dheroNode){
        dHeroNode tHeroNode=head;
        boolean flag=false;
        while(true) {
            if (head.next==null||tHeroNode==null) {
                break;
            }
            if(tHeroNode.no==dheroNode.no){
                flag=true;
                break;
            }else{
                tHeroNode=tHeroNode.next;
            }
        }
        if(flag){
            tHeroNode.nickname=dheroNode.nickname;
            tHeroNode.name=dheroNode.name;
        }
        else{
            System.out.println("未找到相关人物,无法修改。");
        }
    }

    public void del(int no){
        dHeroNode tHeroNode=head;
        boolean flag=false;
        while(true){
            if(head.next==null){
                break;
            }if(tHeroNode==null){
                break;
            }if(tHeroNode.no==no){
                flag=true;
                break;
            }
            tHeroNode=tHeroNode.next;
        }
        if(flag){
            tHeroNode.pre.next=tHeroNode.next;
            if(tHeroNode.next!=null)tHeroNode.next.pre=tHeroNode.pre;
        }
        else{
            System.out.printf("未找到no=[%d]的节点\n",no);
        }
    }

}
  • 删除5号不存在的英雄时
    在这里插入图片描述
  • 删除1号英雄时:
    在这里插入图片描述
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值