Java中双向链表详解及实例

Java中双向链表详解及实例

什么是双向链表?

双向链表是一种经典的线性数据结构,它不仅能够支持插入、删除操作,而且还能够支持在链表中任何位置进行查找操作。

双向链表的每个节点都有两个指针,分别是指向前驱节点和后继节点的指针,这样就可以通过前向和后向遍历节点,从而实现各种操作。

双向链表的定义

下面是Java语言中双向链表的定义:

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

    Node(int data) {
        this.data = data;
        this.prev = null;
        this.next = null;
    }
}

其中,data表示节点中的数据,prev表示节点的前驱节点,next表示节点的后继节点。

双向链表的基本操作

双向链表的基本操作包括插入、删除和查找,下面分别讲解。

插入操作

双向链表的插入操作有三中情况:

  1. 在双向链表的头部插入节点
  2. 在双向链表的尾部插入节点
  3. 在双向链表的中间插入节点

在双向链表的头部插入节点

在双向链表的头部插入节点的代码如下:

public void addFirst(Node node) {
    if(head == null) {
        head = node;
        tail = node;
    } else {
        node.next = head;
        head.prev = node;
        head = node;
    }
}

说明:

  • 如果链表为空,将新加入的节点同时作为头指针和尾指针。
  • 如果链表不为空,则将新加入的节点与原来的头节点相连,同时将新加入的节点设为头节点。

在双向链表的尾部插入节点

在双向链表的尾部插入节点的代码如下:

public void addLast(Node node) {
    if(tail == null) {
        head = node;
        tail = node;
    } else {
        node.prev = tail;
        tail.next = node;
        tail = node;
    }
}

说明:

  • 如果链表为空,将新加入的节点同时作为头指针和尾指针。
  • 如果链表不为空,则将新加入的节点与原来的尾节点相连,同时将新加入的节点设为尾节点。

在双向链表的中间插入节点

在双向链表的中间插入节点的代码如下:

public void addAfter(Node node, Node newNode) {
    if(node == null || newNode == null) {
        return;
    }
    newNode.prev = node;
    newNode.next = node.next;
    if(node.next != null) {
        node.next.prev = newNode;
    } else {
        tail = newNode;
    }
    node.next = newNode;
}

说明:

  • 首先判断空指针的情况。
  • 将新加入的节点与原节点相连。
  • 注意判断原节点是否为尾节点的情况。

删除操作

双向链表的删除操作也有三中情况:

  1. 删除双向链表的头节点
  2. 删除双向链表的尾节点
  3. 删除双向链表的中间节点

删除双向链表的头节点

删除双向链表的头节点的代码如下:

public void removeFirst() {
    if(head == null) {
        return;
    }
    if(head == tail) {
        head = null;
        tail = null;
    } else {
        head = head.next;
        head.prev = null;
    }
}

说明:

  • 如果链表为空,则直接退出。
  • 如果链表中只有一个节点,则将头指针和尾指针都设为空。
  • 如果链表中不止一个节点,则将头指针设为原来头节点的下一个节点,并将新头节点的前驱指针设为空。

删除双向链表的尾节点

删除双向链表的尾节点的代码如下:

public void removeLast() {
    if(tail == null) {
        return;
    }
    if(head == tail) {
        head = null;
        tail = null;
    } else {
        tail = tail.prev;
        tail.next = null;
    }
}

说明:

  • 如果链表为空,则直接退出。
  • 如果链表中只有一个节点,则将头指针和尾指针都设为空。
  • 如果链表中不止一个节点,则将尾指针设为原来尾节点的前一个节点,并将新尾节点的后继指针设为空。

删除双向链表的中间节点

删除双向链表的中间节点的代码如下:

public void removeNode(Node node) {
    if(node == null) {
        return;
    }
    if(head == node) {
        removeFirst();
    } else if(tail == node) {
        removeLast();
    } else {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
}

说明:

  • 首先判断空指针的情况。
  • 如果要删除的是头节点,则直接调用上面的删除头节点的函数。
  • 如果要删除的是尾节点,则直接调用上面的删除尾节点的函数。
  • 如果要删除的节点在中间,则将要删除的节点相邻的节点相连起来即可。

查找操作

双向链表的查找操作可以按照元素值或者位置进行查找。以下示例演示如何通过元素值进行查找:

public Node findNode(int data) {
    Node cur = head;
    while(cur != null) {
        if(cur.data == data) {
            return cur;
        }
        cur = cur.next;
    }
    return null;
}

说明:

  • 从头节点开始遍历整个链表。
  • 如果节点的元素值等于要查找的值,则返回该节点。
  • 如果遍历完整个链表都没有找到对应的节点,则返回空指针。

双向链表的测试示例

下面展示如何对上述代码进行测试:

public class Test {
    public static void main(string[] args) {
        DoublyLinkedList list = new DoublyLinkedList();
        list.addFirst(new Node(1));
        list.addFirst(new Node(2));
        list.addFirst(new Node(3));
        list.addLast(new Node(4));
        list.addLast(new Node(5));
        list.removeLast();
        list.removeFirst();
        Node node = list.findNode(2);
        list.removeNode(node);
    }
}

说明:

  • 首先创建一个双向链表对象。
  • 对链表进行一系列的插入、删除和查找操作。
  • 最后打印出链表来查看结果。

双向链表的应用场景

双向链表可以用于许多数据存储的场景,比如某些排序算法的实现,也可以作为其他数据结构的底层实现,比如Java集合框架中的LinkedList类就是基于双向链表实现的。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中双向链表详解及实例 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • ZeroMQ接口函数之 :zmq_disconnect – 断开一个socket的连接

    ZeroMQ接口函数之 :zmq_disconnect – 断开一个socket的连接 zmq_disconnect(void *socket, const char *endpoint)函数用于断开一个已建立连接的socket。这个函数的调用方式如下: int zmq_disconnect (void *socket, const char *endpoi…

    其他 2023年3月28日
    00
  • Mac OS X 系统下安装和部署Egret引擎开发环境

    以下是关于“Mac OS X 系统下安装和部署Egret引擎开发环境”的完整攻略。 准备工作 首先,需要确认你的电脑已经安装了以下软件: Node.js Git Egret Wing 如果还没有安装,可以在官网下载进行安装。 安装依赖项,在终端输入以下命令: sudo npm install -g egret 以上命令将会全局安装 Egret 框架,这是开发…

    other 2023年6月26日
    00
  • PHP学习 运算符与运算符优先级

    PHP学习:运算符与运算符优先级攻略 1. 运算符优先级概述 在PHP中,运算符优先级决定了表达式中运算符执行的顺序。当一个表达式中存在多个运算符时,按照优先级规则逐个执行运算符,以确定表达式的最终结果。以下是PHP中常见的运算符优先级(从高到低): 递增/递减运算符 (++,–) 一元运算符 (+,-,!) 乘法运算符 (*,/,%) 加法运算符 (+,…

    other 2023年6月28日
    00
  • list的foreach方法获取下标

    以下是使用List的foreach方法获取下标的攻略: 步骤1:了解List的foreach方法 List的foreach方法是一种遍历List集合的方法,可以用于对List中的每个元素进行操作。foreach方法接受一个函数作为参数,该函数在遍历List时被调用。在该函数中,可以使用Java 8中的Lambda表达式来获取List中的元素和下标。 步骤2:…

    other 2023年5月6日
    00
  • 小度wifi蓝屏问题 小度wifi蓝屏解决方法(图文)

    小度WiFi蓝屏问题及解决方法 问题背景 近期,有部分用户反馈使用小度WiFi时出现蓝屏现象。此问题严重影响用户的使用体验,迫切需要解决方案。 问题原因 在调查过程中,我们发现小度WiFi的蓝屏问题主要是由于设备驱动程序的故障造成的。 解决方法 方法一:升级驱动程序 首先,进入设备管理器,在“网络适配器”中找到小度WiFi。 示例1: 点击桌面左下角的Win…

    other 2023年6月27日
    00
  • 一文轻松了解Python中类的继承

    一文轻松了解Python中类的继承 在 Python 中,我们可以通过类的继承机制来创建一个新的类,它会自动继承父类的属性和方法,同时可以添加一些新的属性和方法来扩充其功能。本文将会深入探讨 Python 中类的继承,包括如何继承以及如何调用父类的方法和属性等知识点。 如何实现类的继承 在 Python 中,我们可以通过在子类声明时,将父类作为参数传递来实现…

    other 2023年6月27日
    00
  • Android Studio和阿里云数据库实现一个远程聊天程序

    Android Studio和阿里云数据库实现一个远程聊天程序攻略 简介 本攻略将详细讲解如何使用Android Studio和阿里云数据库来实现一个远程聊天程序。我们将使用Java语言和阿里云的云数据库服务来搭建一个安全可靠的聊天系统。 步骤 步骤一:创建阿里云数据库 登录阿里云控制台,进入云数据库RDS页面。 创建一个新的RDS实例,选择适合的数据库引擎…

    other 2023年9月6日
    00
  • Java基础知识总结之继承

    Java基础知识总结之继承 一、继承概述 Java中的继承是一种重要的代码重用方式,可以让类之间存在“父子关系”,子类可以继承父类的属性和方法,并可以增加自己的属性和方法。 Java中的类可以分成三种:父类、子类和接口。父类和子类之间存在的“父子关系”,是指子类继承了父类的部分属性和方法,从而可以重用父类的代码,减少代码重复。接口则是一种约定,用于定义类具有…

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部