Java数据结构之链表--双向链表

106 阅读2分钟

双向链表

双向链表是链表中常见的一个,每一个节点中存储着前一个结点和后一个结点的地址。

双向链表结点的结构代码

class DoubleNode {

    //这里把成员变量定义为public只是为了省略set/get方法,实际开发不可以这样写哦
    public int no;
    public String name;
    public DoubleNode next;//指向下一个节点,默认为null
    public DoubleNode pre;//指向前一个结点,默认为null

    //构造器
    public DoubleNode(int no, String name) {
        this.no = no;
        this.name = name;
    }
    @Override
    public String toString() {
        return "DoubleNode{" +
                "no=" + no +
                ", name='" + name + 
                '}';
    }
}

双向链表的实现

class DoubleLinkedList{
    //初始化一个头节点,头节点不需要动
    private DoubleNode head = new DoubleNode(0,"");
    //返回头节点
    public DoubleNode getHead(){
        return this.head;
    }

    //遍历双向列表
    public void list(){
        //辅助遍历temp
        DoubleNode temp = head.next;
        if (head.next == null){
            System.out.println("双向列表为空");
        }
        while (true){
            if (temp == null){
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }

    //向双向链表添加数据
    public void add(DoubleNode node){
        //辅助变量
        DoubleNode temp = head;

        while (true){//找到链表的最后
            if (temp.next == null){
                break;
            }
            //继续后移
            temp = temp.next;
        }
        //添加数据
        temp.next = node;
        node.pre = temp;

    }

    //双向链表更新结点(和单向列表一样)
    public void update(DoubleNode newNode){
        //判断是否为空
        if(head.next == null){
            System.out.println("链表为空");
        }
        //不为空,找到想要修改的节点(根据编号no)
        DoubleNode temp = head.next;
        boolean flag = false;//节点是否存在
        while (true){
            if (temp == null){
                break;
            }
            if (temp.no == newNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        //根据false是否找到节点
        if (flag){//找到了
            temp.name = newNode.name;
        }else {//没有找到
            System.out.println("没有找到与之对应编号的节点,无法修改");
        }
    }

    //双向链表删除结点
    public void delete(int index,DoubleNode head){

        //因为不需要找到前一个节点(自我删除),所以直接指向head的next
        //单链表的删除想要找前一个地址,所以想要在head就开始找(为了保证要删除第一个)
        //因为如果直接head=next,那么第一步就到了第一个元素,导致无法删除第一个
        DoubleNode temp = head.next;
        boolean flag = false;//标志是否找节点
        while (true){
            if (temp == null){
                break;
            }
            if (temp.no == index){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            temp.pre.next = temp.next;
            //如果删除的最后一个,那么下面就会出现问题
            //因为temp.next就是null了,如果再pre就会导致空指针异常
            //所以我们要判断,如果是最后一个节点,就不要执行下面的语句
            if (temp.next != null){
                temp.next.pre = temp.pre;
            }
        }
    }

}

测试代码

public class DoubleLinkedListTest {

    public static void main(String[] args) {
        //测试双向链表
        DoubleNode node1 = new DoubleNode(1, "曹操");
        DoubleNode node2 = new DoubleNode(2, "刘备");
        DoubleNode node3 = new DoubleNode(3, "关羽");
        DoubleNode node4 = new DoubleNode(4, "张飞");
        DoubleLinkedList doubleLinkedList  = new DoubleLinkedList();
        //添加英雄人物
        doubleLinkedList.add(node1);
        doubleLinkedList.add(node2);
        doubleLinkedList.add(node3);
        doubleLinkedList.add(node4);
        doubleLinkedList.list();
        //修改测试
        DoubleNode node5 = new DoubleNode(4, "袁术");
        doubleLinkedList.update(node5);
        System.out.println("====================================================================================");
        doubleLinkedList.list();
        //删除测试
        doubleLinkedList.delete(1,doubleLinkedList.getHead());
        doubleLinkedList.list();
    }
}