一、基本介绍

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

对比于单链表

  • 单向链表查找的方向只能是一个方向,而双链表可以向前或者向后查找
  • 单链表在删除节点时不能自我删除,需要依靠被删除节点的前一个节点来辅助删除,而双链表则可以自我删除。
  • 单链表在插入节点时只能在当前节点后插入,双向链表可以在当前节点前或后插入节点。
  • 与单链表相比,双链表虽然在使用时比较方便,但需要多定义一个指向前一个节点的指针空间,并且底层的实现和维护相对于单链表都比较繁琐,所以一般在效率相近的情况下,会优先使用单链表。

二、双向链表的基本使用

1、先定义一个双链表结构

class Node2 {
    //这里为了方便就将变量修饰为public
    public int id;
    public int data;
    public Node2 next;
    public Node2 pre;
    //无参构造器
    public Node2() {
    }
    //带参构造器
    public Node2(int id, int data) {
        this.id = id;
        this.data = data;
    }
    //重写toString方法
    @Override
    public String toString() {
        return "Node2{" + "id=" + id + ", data=" + data + '}';
    }
}

2、我们再定义一个类来添加基本的增删改查操作

class DoubleLinkedList1 {
    //我们这里使用带头节点的双链表,是否带头节点根据具体需要而定
    private Node2 head = new Node2();

    //自定义顺序添加节点,默认id唯一,不可重复添加
    public void add(Node2 node) {
        Node2 temp = head;
        boolean flag = false;//判断节点是否已经存在
        while (true) {//遍历
            if (temp.next == null) {
                break;
            }
            if (node.id == temp.next.id) {//已经存在
                flag = true;
                break;
            }
            temp = temp.next;//指针后移
        }
        if (flag) {
            System.out.printf("节点%d已经存在,不可重复添加!\n", node.id);
        } else {
            temp.next = node;
            node.pre = temp;
        }
    }

    public void addByOrder(Node2 node) {
        Node2 temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.id > node.id) {
                break;
            } else if (temp.next.id == node.id) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            System.out.println("英雄已经存在,不能重复添加");
        } else {
            if (temp.next != null) {

                temp.next.pre = node;
            }
            node.next = temp.next;
            temp.next = node;
            node.pre = temp;
        }
    }

    //删除节点
    public void delete(int id) {
        if (head.next == null) {
            System.out.println("链表为空!");
            return;
        }
        Node2 temp = head.next;
        boolean flag = false;//标志是否找到要删除的节点
        while (true) {//遍历
            if (temp == null) {//遍历到最后一个节点还未找到
                break;
            }
            if (id == temp.id) {//找到要删除的节点
                flag = true;
                break;
            }
            temp = temp.next;//指针后移
        }
        if (flag) {
            temp.pre.next = temp.next;
            temp.next.pre = temp.pre;
        } else {
            System.out.printf("未找到id为%d的节点\n",id);
        }
    }

    public void update(Node2 node) {
        if (head.next == null) {
            System.out.println("链表为空!");
            return;
        }
        Node2 temp = head.next;
        boolean flag = false;
        while (true) {//遍历
            if (temp == null) {
                break;
            }
            if (node.id == temp.id) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.data = node.data;
        } else {
            System.out.printf("未找到id为%d的节点\n",node.id);
        }
    }

    //遍历
    public void list() {
        if (head.next == null) {
            System.out.println("链表为空!");
            return;
        }
        //辅助节点,用来遍历
        Node2 temp = head.next;
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }

    }
}

3、写一个Demo来测试

/**
 * @author dankejun
 * @create 2020-04-01 11:20
 */
public class DoubleLinkedListExer {
    public static void main(String[] args) {
        Node2 node1 = new Node2(1,10);
        Node2 node2 = new Node2(2,20);
        Node2 node3 = new Node2(3,30);
        Node2 node4 = new Node2(4,40);

        DoubleLinkedList1 list = new DoubleLinkedList1();
//        list.add(node1);
//        list.add(node2);
//        list.add(node3);
//        list.add(node4);
//        System.out.println("当前的双链表为:");
//        list.list();

        list.addByOrder(node1);
        list.addByOrder(node4);
        list.addByOrder(node3);
        list.addByOrder(node2);
        System.out.println("当前的双链表为:");
        list.list();

        Node2 node5 = new Node2(2, 50);
        list.update(node5);
        System.out.println("修改后的双链表为:");
        list.list();

        list.delete(3);
        System.out.println("删除后的双链表为:");
        list.list();
    }
}

测试结果:

java 单链表快排 java单链表和双链表的区别_java