双链表与单链表的区别是,单链表只能沿着一个方向去查找,双链表可以沿着正向和反向进行查找。如下图所示。单链表的实现可以看我前面的博客

 

java双表联查分页展示所有数据 java双链表实现_java双表联查分页展示所有数据

实现原理

在原来单链表的属性中会添加一个pre(存放前一个节点的地址),原有属性不变。

查找:和单链表的查找是完全一样的,只不过,通过反方向也可以进行查找

修改:和单链表的修改是一样的。

删除:删除有点特殊,单链表是将一个节点移除之后,将该节点的前一个节点的next指向该节点的下一个节点。但是双链表有点不同,除了将一个方向的指针移动之外,还要操作反方向的指针,即将删除节点的下一个节点的前驱指向删除节点的上一个节点,即完成删除。

添加:添加操作也有点不同,之前单链表是将节点添加到该链表的最后一个节点之后,将最后一个节点的next指向添加的节点即可。双链表也是将节点添加到最后一个节点之后,只不过还要将添加节点的前驱指向最后一个节点,实现双向链接。

实现代码

package cn.mrlij.linkedlist;

/**
 * 双向链表的实现
 */
public class DoubleLinkedList {
    public static void main(String[] args) {
        DoubleLinkedListDemo s = new DoubleLinkedListDemo();
        s.add(new HeroNode2(1,"张飞","小张"));
        s.add(new HeroNode2(2,"刘备","小刘"));
        s.add(new HeroNode2(3,"关羽","小关"));
//        s.del(3); //删除
        s.update(new HeroNode2(3,"曹操","小曹"));
        s.list();
    }
}
class DoubleLinkedListDemo{
    //创建一个头结点,初始化数据,头结点不要动,不放具体的数据

    private HeroNode2 head = new HeroNode2(0,"","");
    public HeroNode2 getHead() {
        return head;
    }
    //删除节点 与单链表不同的是,要删除节点.next.pre指向 要删除节点的前一个节点(排除删除最后一个节点的情况)
    public void del(int no) {
        if(head.next == null) {
            System.out.println("链表为空!");
            return;
        }
        HeroNode2 temp = head;
        boolean flag = false;
        while(true) {
            if(temp.next == null) {
                break;
            }
            if(temp.next.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag) {
            temp.next = temp.next.next;
            //需要做出判断,当删除的是最后一个节点,不作处理就会报空指针异常
            if(temp.next != null){
                temp.next.pre = temp;
            }
//            temp.pre.next = temp.next;
//            if(temp.next!=null){
//                temp.next.pre = temp.pre;
//            }
//            temp.pre.next = temp.next;
//
//            //需要做出判断,当删除的是最后一个节点,就会报空指针异常
//            if(temp.next!=null){
//                temp.next.pre = temp.pre;
//            }

        }else {
            System.out.println("该节点不存在!");
        }
    }
    //修改节点内容
    public void update(HeroNode2 node ) {
        if(head.next == null) {
            System.out.println("链表为空!");
            return;
        }
        HeroNode2 temp = head.next;
        boolean flag = false;
        while(true) {
            if(temp == null) {
                break;
            }
            if(temp.no == node.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag) {
            temp.name = node.name;
            temp.nickname = node.nickname;
        }else {
            System.out.println("不存在该节点!");
        }
    }
    //添加英雄
    public void add(HeroNode2 node) {
        //先找出最后的一个节点,把新加的节点放在最后一个节点的后面
        HeroNode2 temp = head;
        while(true) {
            if(temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = node;
        //与单链表不同的是,添加的节点的前驱指向上一个节点
        node.pre = temp;
    }
    //遍历链表,与单链表不同的是,可以从不同的方向遍历双向链表,即可以从前面遍历,也可以从后面遍历
    public void list() {
        HeroNode2 temp = head;
        //首先判断链表是否为空
        if(temp.next == null) {
            System.out.println("链表为空!");
            return;
        }
        while(true) {
            if(temp.next == null) {
                break;
            }
            System.out.println(temp.next);
            temp = temp.next;
        }
    }
}
class HeroNode2{
    public int no;//英雄编号
    public String name;//人名
    public String nickname;//绰号
    public HeroNode2 next;//下一个节点
    public HeroNode2 pre;//前一个节点
    public HeroNode2(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }
    @Override
    public String toString() {
        return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
    }
}