自学内容网 自学内容网

线性表的链式存储结构————双链表(java)

线性表的链式存储结构————双链表(java)


嗨!收到一张超级美丽的风景图,愿你每天都能顺心!
在这里插入图片描述

双链表

在双链表中,由于每个结点既包含一个指向后续结点又包含一个指向前驱结点,所以当访问过一个结点后既可以向后访问每一个结点,也可以一次向前访问每一个结点。因此与单链表相比,在双链表中访问一个结点的前后结点更方便。
在这里插入图片描述

双链表的创建

    private Node head;
    private Node tail;

    private static class Node {
        int data;
        Node next;
        Node prev;

        public Node(int data) {
            this.data = data;
            this.next = null;
            this.prev = null;
        }
    }
  • private Node head;:这是一个私有成员变量,表示链表的头节点。头节点是链表中的第一个节点。
  • private Node tail;:这是一个私有成员变量,表示链表的尾节点。尾节点是链表中的最后一个节点。
  • private int size;:这是一个私有成员变量,表示链表中节点的数量。
  • int data;:存储节点中的数据。
  • Node next;:指向链表中下一个节点的引用。如果当前节点是链表的最后一个节点,则此引用为null。
  • Node prev;:指向链表中前一个节点的引用。如果当前节点是链表的第一个节点,则此引用为null。

Node类的构造函数接受一个整数参数data,并将其赋值给节点的成员变量data。同时,它将next和prev初始化为null,表示这个节点目前没有连接到任何其他节点。

插入数据元素

头插法

在这里插入图片描述

  • 插入数据首先要判断链表是否为空。
  • 如果是空链表头结点=插入的结点=尾结点。
  • 不为空将则将插入节点next指向头结点
  • 调整首结点的前驱为新结点
  • 将新结点设置为首结点
  • 链表长度+1
    public void insertHead(int data){
        Node newNode = new Node(data);
        if (head != null) {
            head.prev = newNode;
            newNode.next = head;
        }
        head = newNode;
    }

尾插法

在这里插入图片描述
47a11.png#pic_center)

  • 插入数据首先要判断链表是否为空。
  • 如果是空链表头结点=插入的结点=尾结点。
  • 不为空将则将插入节点prev指向尾结点
  • 调整尾结点的后继为新结点
  • 将新结点设置为尾结点
  • 链表长度+1
public void insertTail(int data){
        Node newNode = new Node(data);
        if(head == null){
            head = newNode;
        }else {
            tail.next = newNode;
            newNode.prev = tail;
        }
        tail = newNode;
    }

求链表的长度

要计算双链表的长度,可以遍历整个链表并计数节点的数量。

    public int length(){
        int size = 0;
        Node current = head;
        while (current != null){
            size++;
            current = current.next;
        }
        return size;
    }
    public void len(){
        int size = length();
        System.out.println(size);
    }

输出双链表

    public void print(){
        Node current = head;
        while (current != null){
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }

删除双链表中的指定元素

在这里插入图片描述
e.png#pic_center)

  • 定义一个名为delete的公共方法,接收一个整数类型的参数data,表示要删除的节点的数据值。
    初始化一个名为current的变量,将其设置为链表的头节点(head)。
  • 使用一个while循环遍历链表,直到current变为null(即到达链表尾部)。
  • 在循环内部,检查当前节点的数据值是否等于要删除的数据值(current.data == data)。
  • 如果找到了匹配的节点,执行以下操作: a. 如果当前节点不是头节点(即current.prev != null),则将当前节点的前一个节点的next指针指向当前节点的下一个节点(current.prev.next = current.next)。 b. 如果当前节点是头节点(即current.prev == null),则将链表的头节点更新为当前节点的下一个节点(head = current.next)。 c. 如果当前节点不是尾节点(即current.next != null),则将当前节点的下一个节点的prev指针指向当前节点的前一个节点(current.next.prev = current.prev)。
  • 完成删除操作后,直接返回,不再继续遍历链表。
    如果遍历完整个链表都没有找到匹配的节点,那么函数什么也不做,自然结束。
    public void delete(int data){
        Node current = head;
        while (current != null){
            if(current.data == data){
                if(current.prev != null){
                    current.prev.next = current.next;
                }else {
                    head = current.next;
                }
                if(current.next != null){
                    current.next.prev = current.prev;
                }
                return;
            }
            current = current.next;
        }
    }

总代码


public class Dnode {
    private Node head;
    private Node tail;

    private static class Node{
        int data;
        Node next;
        Node prev;
        public Node(int data){
            this.data = data;
            this.next = null;
            this.prev = null;
        }
    }
    //尾插法
    public void insertTail(int data){
        Node newNode = new Node(data);
        if(head == null){
            head = newNode;
        }else {
            tail.next = newNode;
            newNode.prev = tail;
        }
        tail = newNode;
    }
    //长度
    public int length(){
        int size = 0;
        Node current = head;
        while (current != null){
            size++;
            current = current.next;
        }
        return size;
    }
    public void len(){
        int size = length();
        System.out.println(size);
    }
    public void print(){
        Node current = head;
        while (current != null){
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }
    //删除指定元素
    public void delete(int data){
        Node current = head;
        while (current != null){
            if(current.data == data){
                if(current.prev != null){
                    current.prev.next = current.next;
                }else {
                    head = current.next;
                }
                if(current.next != null){
                    current.next.prev = current.prev;
                }
                return;
            }
            current = current.next;
        }
    }

    public static void main(String[] args) {
        Dnode list = new Dnode();
        list.insertTail(1);
        list.insertTail(2);
        list.insertTail(3);
        list.insertTail(4);
        list.print();
        list.len();
        list.delete(2);
        list.print();
    }
}

运行效果

在这里插入图片描述

用Java内部类实现双链表

我们除了自己手写双链表外,Java还提供了一个类来帮助我们快速实现双链表(LinkedList)

API网址
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/LinkedList.html

在这里插入图片描述

在这里插入图片描述

我们直接调用我们需要的方法即可。

import java.util.LinkedList;

public class Dnode {
    public static void main(String[] args) {
        // 创建一个空的双链表
        LinkedList<Integer> Dnode = new LinkedList<>();
        Dnode.addLast(1);
        Dnode.addLast(2);
        Dnode.addLast(3);
        Dnode.addLast(4);
        Dnode.addLast(5);
        StringBuilder output = new StringBuilder();
        for(int value:Dnode){
            output.append(value).append(" ");
        }
        System.out.print(output);
    }
}

由于直接调用的输出格式是列表的格式,所以想直接输出数字,就将其转换为字符串,并遍历循环输出。其他更多的功能大家也可以自己去尝试一下。

结语

本次分享就到这里了,感谢小伙伴的浏览,如果有什么建议,欢迎在评论区留言,如果给小伙伴们带来了一些收获,请留下你的小赞,你的点赞和关注将会成为博主分享每日学习的动力。


原文地址:https://blog.csdn.net/h091616/article/details/140505199

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!