双向链表(动图讲解)-Java数据结构和算法

单向链表基本操作 图解


前言

      对于单向链表来说,查找的方向只能单向的,所以进行删除或插入,我们需要找到目标的前一个结点(无法实现向后查找的弊端)。
      单向链表不能自我删除,借助辅助节点才可以,双向链表则可以查看前驱节点,从而实现自我删除,介绍如下:


一、双向链表的介绍:

1. 见名知义,双向链表可以向前或向后查找;
2. 双向链表删除节点,只需要找到删除的目标节点自身即可;
3. 双向链表插入节点,只要找到插入的位置本身就可以;
4. 所以,双向链表很方便,不需要借助与其他节点就可以实现很多功能;

二、相关操作

1. 新建双向链表的类

      显然,双向链表需要保存它的前驱节点的信息,因此比单向链表的属性会多一个;
      代码如下:

class HeroNode2{
    public int no;		//编号
    public String name;·//姓名
    public String nickname;//绰号
    public HeroNode2 next;//下个节点域
    public HeroNode2 per;//前驱节点域

    //构造器
    public HeroNode2(int n , String name , String nickname){
        this.no = n;
        this.name = name;
        this.nickname = nickname;
    }


    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}

2.删除数据(变化较大,有坑🔺)

1. 因为是双向链表,所以可以实现自我删除节点
2. 直接找到要删除的节点,例如为p
3. p.pre.next = p.next;
4. temp.next.pre = temp.pre;
	相当于p前里面和后面的节点把p节点给覆盖掉了:

在这里插入图片描述

代码如下:

public void delate(int no){
    if(head.next == null){
        System.out.println("链表为空,删除失败....");
        return;
    }

    boolean flag = false;//是否找到待删除结点
    HeroNode2 p = head.next;

    while(true){
        if(p == null){
            break;
        }

        if(p.no == no){
            flag = true;
            break;
        }
        p = p.next;
    }
    if(flag){
        p.per.next = p.next;
        //这里的代码需要注意(如果删除的是最后一个节点.就不需要最后一句话,否则空指针异常)
        if(p.next != null)//待删除的节点不是最后一个才能进行这步
            p.next.per = p.per;
        return;
    }else{
        System.out.println("删除失败,未找到...");
        return;
    }
}

3. 中间添加数据

1. 找到要添加的位置p
2. newNode.next = p;
3. p.pre.next = newNode;
4. newNode.pre = p.pre;
5. p.pre = newNode;
	按照这个顺序,不能先断开p.pre否则会出错

代码如下:

在这里插入图片描述

4.尾部添加数据(稍微变化)

默认尾部添加数据
1. 先找到双向链表的最后;
2. temp.next = newHeroNode
3. newHeroNode.pre = temp:实现双向链表

在这里插入图片描述

代码如下:

public void add(HeroNode2 heroNode){
    //因为head节点不能动,保护原链表
    HeroNode2 temp = head;
    //遍历到最后
    while(temp.next != null){
        temp = temp.next;
    }
    //形成一个双向链表
    temp.next = heroNode;
    heroNode.per = temp;
}

5.修改数据(思路不变)

根据编号修改,所以编号不可以变
1. 判断双链表是否为空,为空处理即可
2. 链表不为空,则遍历查找到编号对应的节点即可
3. 找到之后更新节点信息即可

代码如下:

public void update(HeroNode2 newHeroNode){
    if(head.next == null){
        System.out.println("链表为空");
        return;
    }

    HeroNode2 p = head.next;
    boolean flag = false;
    while(true){
        if(p.no == newHeroNode.no){
            flag = true;
            break;
        }
        if(p == null){
            break;
        }
        p = p.next;
    }
    if(flag){
        p.name = newHeroNode.name;
        p.nickname = newHeroNode.nickname;
    }else{
        System.out.println("未找到要修改的英雄,请重试");
        return;
    }
}

6.双向链表的遍历(无变化)

1. 遍历的方式和单链表相同:
2. 可以双向遍历(向前或向后遍历)

代码如下:

public void show(){
    if(head.next == null){
        System.out.println("链表为空");
        return;
    }
    HeroNode2 temp = head.next;
    while(true){
        if(temp == null){
            break;
        }
        System.out.println(temp);
        temp = temp.next;
    }
}

总结

1. 删除和添加节点的时候仅需找到要删除或者添加的位置即可,不需要找到前面一个;
2. 删除结点的时候应注意是否是最后一个节点,最后一个节点注意避坑;
3. 注意在中间节点添加数据的操作顺序;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值