双向链表

152 阅读2分钟

单链表的缺点:

  • 只能从头节点开始访问整个链表
  • 单链表在删除时需要借助辅助节点,不能自我删除,需要找到要删除节点的前一个节点然后进行删除操作。

双向链表:

  由于单链表的缺点,延伸出了双向链表,双向链表的节点中比单链表多了一个pre,指向该节点的前驱节点,在访问链表时既可以向前访问也可以向后访问。而且双向链表中的节点可以自我删除。

//temp即是当前要删除的节点
temp.pre.next = temp.next;
temp.next.pre = temp.pre;

  注意在双向链表进行删除时,要判断删除的节点是否为最后一个节点,如果不加判断条件使用上述两行代码则会报错,如果temp为最后一个节点,则temp.nextnull,所以temp.next.pre会出错。当为最后一个节点时,只需要temp.pre.next = temp.next;即可。

代码实现(java)

package com.doublelinkedlist;

public class LinkedList2 {
    public static void main(String[] args) {
        System.out.println("双向链表测试:");
        DoubleLinkedList List2 = new DoubleLinkedList();

        Node2 node1 = new Node2(1, "张三", "第一");
        Node2 node2 = new Node2(2, "李四", "第二");
        Node2 node3 = new Node2(3, "王五", "第三");
        List2.addNode2(node1);
        List2.addNode2(node2);
        List2.addNode2(node3);
        //添加节点后遍历
        List2.showLinkedList2();

        //修改节点的值,传入no值和修改后的信息,与单链表相同
        List2.changeNode2(2, "张张", "第0");
        List2.showLinkedList2();

        //删除节点,传入no值
        List2.del2(3);
        List2.showLinkedList2();
    }
}

class Node2 {
    public int no;
    public String name;
    public String nickName;
    public Node2 next;
    public Node2 pre;

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

class DoubleLinkedList {
    private Node2 head = new Node2(0, "", "");

    //插入节点
    public void addNode2(Node2 node) {
        Node2 temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = node;
        node.next = null;
        node.pre = temp;
    }

    //修改节点的值,此处要用no做判断,no不能被修改
    public void changeNode2(int no, String name, String nickName) {
        Node2 temp = head;
        Boolean flag = false;
        if (temp.next == null) {
            System.out.println("链表为空不能修改!");
        }
        while (temp.next != null) {
            if (temp.next.no == no) {
                temp.next.name = name;
                temp.next.nickName = nickName;
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag == false) {
            System.out.println("链表中没有该节点!");
        }
    }

    //根据no删除对应节点
    public void del2(int no) {
        Node2 temp = head.next;
        Boolean flag = false;
        if (temp == null) {
            System.out.println("链表为空,不能删除!");
            return;
        }
        while (temp != null) {
            if (temp.no == no) {
                temp.pre.next = temp.next;
                if (temp.next != null) {
                    temp.next.pre = temp.pre;
                }
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag == false) {
            System.out.println("链表中没有该节点!");
        }
    }

    //遍历输出链表中节点信息
    public void showLinkedList2() {
        Node2 temp = head;
        if (temp.next == null) {
            System.out.println("链表为空!!!");
        }
        while (temp.next != null) {
            System.out.printf("no = %d name = %s nickName = %s;\n", temp.next.no, temp.next.name, temp.next.nickName);
            temp = temp.next;
        }
    }
}