java数据结构与算法之双向链表(含完整 Demo)

777 阅读4分钟

其他数据结构文章

上一章给大家介绍了单向链表的一些操作,本章给大家介绍数据结构之双向链表

什么是双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

百度百科

图片辅助图:

image.png

在来看看节点类(HeroNode2):

image.png

  • id 后面会通过 id 来使双向链表排序
  • name 随便一个参数即可
  • next 保存的是下一个元素(最后一个 next 为 null)
  • pre 保存的是上一个元素(第一个元素的 pre为 null)

添加(add)元素

分析:

  • 默认添加元素是吧元素添加到最后一个位置,所以只需要遍历链表中的所有数据,当 next 为 null 的时候,表示当前在最后一个位置

先来看看代码:

public class DoubleLinkedList {

    //标识第一个节点位置,不存储元素
    private HeroNode2 head = new HeroNode2(0, "");

    public void add(HeroNode2 heroNode2) {
        HeroNode2 temp = head;

        while (temp.next != null) {
            //链表后移
            temp = temp.next;
        }

        //添加最后一个元素
        temp.next = heroNode2;
        heroNode2.pre = temp;
    }
 }

使用:

        doubleLinkedList.add(new HeroNode2(1,"白骨精"));
        doubleLinkedList.add(new HeroNode2(2,"李云龙"));
        doubleLinkedList.add(new HeroNode2(3,"宋江"));
        doubleLinkedList.add(new HeroNode2(4,"孙悟空"));
        doubleLinkedList.add(new HeroNode2(5,"刘国强"));
        
        System.out.println("\n原数据为:");
        doubleLinkedList.show();

运行结果为:

原数据为:
HeroNode2{id=1, name='白骨精'}
HeroNode2{id=2, name='李云龙'}
HeroNode2{id=3, name='宋江'}
HeroNode2{id=4, name='孙悟空'}
HeroNode2{id=5, name='刘国强'}

辅助图:

image.png

show显示的方法:

public void show() {
        if (head.next == null) {
            System.out.println("链表元素为unll不能打印");
            return;
        }

        HeroNode2 temp = head;
        while (temp.next != null) {
            //后移temp
            temp = temp.next;
            System.out.println(temp);
        }
    }

这个显示的方法很好理解,循环判断tempnext是否为 null ,!=null就一直打印即可

删除(remove)元素

分析:

删除元素和单链表的思路一样,需要通过传入删除的 id 来判断链表中是否有该 id,最后删除即可

来看看代码:

  //根据 id 删除元素
    public void remove(int id) {
        if (head.next == null) {
            System.out.println("链表为null,不能删除");
            return;
        }

        //从第一个元素开始循环
        HeroNode2 temp = head.next;

        //用来标识id 是否相同,如果 temp.id == id 标识链表中有一样的元素,可以删除
        boolean flag = false;

        while (temp != null) {
            if (temp.id == id) {
                flag = true;
                break;
            }
            //后移 temp
            temp = temp.next;
        }

        if (flag) {
            temp.pre.next = temp.next;

            if (temp.next != null) {
                temp.next.pre = temp.pre;
            }
        } else {
            System.out.println("没有找到元素" + id);
        }
    }

使用:

        doubleLinkedList.remove(2);
        doubleLinkedList.remove(5);
        System.out.println("删除元素后数据为:");
        doubleLinkedList.show();

最终结果为:

删除元素后数据为:
HeroNode2{id=1, name='白骨精'}
HeroNode2{id=3, name='宋江'}
HeroNode2{id=4, name='孙悟空'}

辅助图:

image.png

替换元素

分析:

替换元素和单链表思路也是一样的,需要传入一个被替换的元素,然后将元素替换了即可

首先需要判断传入的 id 在链表中是否存在.如果存在则能够替换,不存在则不能替换

来看看代码吧:

//替换元素
    public void upData(HeroNode2 heroNode2) {
        if (head.next == null) {
            System.out.println("不能替换,数据为空");
            return;
        }

        HeroNode2 temp = head.next;

        boolean flag = false;

        while (temp != null) {
            if (temp.id == heroNode2.id) {
                flag = true;
                break;
            }
            //后移 temp
            temp = temp.next;
        }

        if (flag) {
            temp.name = heroNode2.name;
            temp.id = heroNode2.id;

        } else {
            System.out.println("链表中没有" + heroNode2.name + "元素");
        }
    }

使用:

        System.out.println("\n原数据为:");
        doubleLinkedList.show();

        HeroNode2 newHero = new HeroNode2(1, "李逵");
        doubleLinkedList.upData(newHero);
        System.out.println("\n替换元素后数据为:");
        doubleLinkedList.show();

最终结果为:

原数据为:
HeroNode2{id=1, name='白骨精'}
HeroNode2{id=2, name='李云龙'}
HeroNode2{id=3, name='宋江'}
HeroNode2{id=4, name='孙悟空'}
HeroNode2{id=5, name='刘国强'}

替换元素后数据为:
HeroNode2{id=1, name='李逵'}
HeroNode2{id=2, name='李云龙'}
HeroNode2{id=3, name='宋江'}
HeroNode2{id=4, name='孙悟空'}
HeroNode2{id=5, name='刘国强'}

辅助图:

image.png

根据 id 来排序

分析:

这个也和单链表思路一模一样,首先需要通过判断 id 比大小,如果head.next.id > heroNode2.id(传入的 id) 那么就终止循环,将链表插入到当前节点中

首先还是先看代码:

 //根据 id 来排序
    public void addId(HeroNode2 heroNode2) {
        HeroNode2 temp = head;

        while (temp.next != null) {
            if (temp.next.id > heroNode2.id) {
                break;
            }
            temp = temp.next;
        }

        heroNode2.next = temp.next;

        if (temp.next != null) {
            temp.next.pre = heroNode2;
        }

        heroNode2.pre = temp;

        temp.next = heroNode2;
    }

使用:

        doubleLinkedList.addId(new HeroNode2(5,"刘国强"));
        doubleLinkedList.addId(new HeroNode2(1,"白骨精"));
        doubleLinkedList.addId(new HeroNode2(4,"孙悟空"));
        doubleLinkedList.addId(new HeroNode2(2,"李云龙"));
        doubleLinkedList.addId(new HeroNode2(3,"宋江"));
        
        System.out.println("\n原数据为:");
        doubleLinkedList.show();

运行结果为:

原数据为:
HeroNode2{id=1, name='白骨精'}
HeroNode2{id=2, name='李云龙'}
HeroNode2{id=3, name='宋江'}
HeroNode2{id=4, name='孙悟空'}
HeroNode2{id=5, name='刘国强'}

图解:

image.png

最终的结果为:

image.png

可能您看了有点迷糊,数据结构就是这样,一点点不一样就会引发很大的反映,虽然就这么点代码,我也总结了好几天.

个人建议:想要学双向链表之前单链表的 增/删/改/根据 id 增加 都必须会写!,会了单向链表双向链表很好理解

还有就是,数据结构,只可意会不可言传!

加油!

完整代码

猜你喜欢:

数据结构与算法目录

原创不易,您的点赞就是对我最大的支持!