链表-双向链表

Posted 奔跑的路奇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表-双向链表相关的知识,希望对你有一定的参考价值。

双向链表

单向链表: 链接.

什么是双链表?


	双链表顾名思义,就是链表由单向的链变成了双向链。 
	使用这种数据结构,我们可以不再拘束于单链表的单向创建于遍历等操作,大大减少了在使用中存在的问题。
	

双向链表图
在这里插入图片描述
在单链表中,有一个指针(该指针是指向下一个节点),而指针域则负责链表之间的“联系”。 而在双向链表中,我们需要有两个指针,一个负责向后连接,一个负责向前连接。

1.1 双向链表的结构


//双向链表的结构
class HeroNode2{

    public int no;//编号,删除和修改就是按编号来进行
    public String name;//名字
    public String nickName;//昵称
    public HeroNode2 next; //指向下一个节点 默认null
    public HeroNode2 pre;//指向前一个节点,默认null

    public HeroNode2(int no,String name,String nickName){
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    //为了显示方法,重写toString方法
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\\'' +
                ", nickName='" + nickName  +
                '}';
    }
}

1.2 双向链表的遍历


    //先初始化一个 头节点,头节点不动 , 不存放具体的数据
    private HeroNode2 head = new HeroNode2(0,"","");


    //头节点
    public HeroNode2 getHead() {
        return head;
    }

    //遍历双向链表
    /**
     * 显示链表中的全部数据信息
     */
    public void list(){
        //先判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //因为头节点,不能动 , 因此我们需要一个辅助遍历来遍历
        HeroNode2 temp = head.next;
        while (true){
            //判断是否是链表的最后
            if (temp == null){
                break;
            }
            //输出节点的信息
            System.out.println(temp);
            //将temp后移,一定要后移,否则会死循环
            temp = temp.next;
        }
    }
    

1.3 双向链表添加:添加一个节点到双向链表的最后


    //双向链表添加:添加一个节点到双向链表的最后
    public void add(HeroNode2 heroNode){

        //因为 head不动 ,因此我们小一个辅助遍历 temp
        HeroNode2 temp = head;
        //遍历链表找到最后
        while (true){
            //当
            if (temp.next == null){
                break;
            }
            //如果没有找到最后 , 就将temp后移
            temp = temp.next;
        }
        //当退出while循环时, temp 就指向了链表的最后
        temp.next = heroNode;
        heroNode.pre = temp; //形成一个双向链表
    }
    

1.4 双向链表修改节点内容

    //修改节点内容:双向和单向修改一样
    public void update(HeroNode2 newHeroNoe){
        //判断是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //找到需要修改的节点 , 根据 no 编号
        //先定义一个辅助变量
        HeroNode2 temp = head.next;
        boolean flag = false; //表示没找打到该节点
        while (true){
            if (temp == null){
                break; //到链表的最后,没有找到要修改的节点
            }
            if (temp.no == newHeroNoe.no){ //找到了
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //根据flag判断是否找到
        if (flag){
            //找到了,修改
            temp.name = newHeroNoe.name;
            temp.nickName = newHeroNoe.nickName;
        }else {
            //没有找到
            System.out.println("没有找到该编号的节点,不能修改:"+newHeroNoe.no);
        }

    }
    

1.5 双向链表修改节点内容


    //从双向链表删除一个节点
    //双向链表可以直接找到这个节点,找到后可以自己删除
    //
    public void delete(int no){

        //判断当前链表是否为空
        if (head.next == null){
            System.out.println("链表为空,无法删除");
            return;
        }

        HeroNode2 temp = head.next;//辅助变量
        boolean flag = false;//表示没有找到删除节点的前一个节点
        while (true){
            if (temp == null){ //没有找到要删除的节点,找到了链表的最后
                break;
            }
            if (temp.no == no){
                flag = true; //找到了
                break;
            }
            temp = temp.next;//后移
        }

        //判断flag
        if (flag){
            //找到,可以删除
//            temp.next = temp.next.next; //但链表的删除方式
            temp.pre.next = temp.next; //将
            //如果是最后一个节点就不需要执行这句话,否则会有空指针异常
            if (temp.next != null) {
                temp.next.pre = temp.pre;//将要删除节点的 next和pre 都去掉(但如果是最后一个,最后一个后面没有节点了)
            }
        }else {
            System.out.println("没有找到要删除的节点,该节点不存在:"+no);
        }
    }

1.6 测试上面所写的方法


public class DoubleLinkedListDemo {

    public static void main(String[] args) {
        System.out.println("双向链表的测试");
        //先创建节点
        HeroNode2 heroNode = new HeroNode2(1, "邓超", "天霸");
        HeroNode2 heroNode1 = new HeroNode2(2, "陈赫", "动霸");
        HeroNode2 heroNode2 = new HeroNode2(3, "鹿晗", "tue");
        HeroNode2 heroNode3 = new HeroNode2(4, "杨颖", "baby");

        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
        doubleLinkedList.add(heroNode);
        doubleLinkedList.add(heroNode1);
        doubleLinkedList.add(heroNode2);
        doubleLinkedList.add(heroNode3);
        doubleLinkedList.list();

        System.out.println("修改后的链表");
        HeroNode2 heroNode4 = new HeroNode2(4, "ab", "study");
        doubleLinkedList.update(heroNode4);
        doubleLinkedList.list();

        System.out.println("删除节点");
        doubleLinkedList.delete(4);
        doubleLinkedList.list();

    }
}

最后,如果有问题,希望指正,一起进步。

以上是关于链表-双向链表的主要内容,如果未能解决你的问题,请参考以下文章

双向链表JAVA代码

7L-双线链表实现

链表的java实现(单向双向链表,单向链表的反转)

链表的java实现(单向双向链表,单向链表的反转)

数据结构之带头结点的循环双向链表详细图片+文字讲解

静态链表循环链表双向链表(C代码实现)