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日

相关文章

  • Windows Server 2012下手动配置IIS的文件夹访问权限

    Windows Server 2012下手动配置IIS的文件夹访问权限 在Windows Server 2012操作系统下,为了更好的保护网站数据的安全,我们通常需要手动配置IIS的文件夹访问权限。本文将介绍如何在Windows Server 2012下手动配置IIS的文件夹访问权限的步骤和方法。 步骤一:打开IIS Manager 在 Windows Se…

    其他 2023年3月28日
    00
  • 详解如何热重启golang服务器

    下面是关于如何热重启Golang服务器的详细攻略: 简介 热重启指在运行中的程序重启时,不需要中断或停止该程序的服务,而是在后台保持其服务的情况下,重新加载代码和配置文件,并使新代码和文件生效。 Golang 提供了一些方便的库和工具,可以让我们实现 HTTP 服务器的热重启,使得服务的高可用性和无停机更新成为可能。 方式1:graceful gracefu…

    other 2023年6月27日
    00
  • win11刚开机cpu就满了怎么办?win11刚开机cpu占用100%解决方案

    针对“win11刚开机cpu就满了怎么办?win11刚开机cpu占用100%解决方案”这个问题,我给出以下完整的攻略: 问题原因分析 首先需要分析导致 CPU 占用率达到100% 的原因,这主要包括以下几个方面: 进程异常:可能有某些进程异常,一直占用 CPU。 资源竞争:某些高 CPU 使用率的程序在同一时间竞争计算机资源。 系统服务异常:有时某些系统服务…

    other 2023年6月26日
    00
  • Javascript中字符串相关常用的使用方法总结

    Javascript中字符串相关常用的使用方法总结 在Javascript中,字符串是一种常见的数据类型。在日常的开发过程中,对于字符串的处理十分重要。本篇文章将对Javascript中字符串相关常用的使用方法进行总结,旨在帮助读者更加深入地理解和运用字符串类型的相关知识。 1. 创建字符串 使用单引号创建一个字符串: var str1 = ‘hello w…

    other 2023年6月20日
    00
  • PHP预定义超全局数组变量小结

    PHP预定义超全局数组变量小结 在PHP中,有一些特殊的全局数组变量,被称为预定义超全局数组变量。这些变量在任何作用域中都可用,无需使用global关键字。下面是一些常用的预定义超全局数组变量及其功能的详细说明。 1. $_GET $_GET是一个关联数组,用于获取通过URL参数传递给当前脚本的值。它可以用于从URL中获取用户输入的数据。以下是一个示例: /…

    other 2023年7月29日
    00
  • mac下jenkins安装步骤

    Mac下Jenkins安装步骤 Jenkins是一个流行的开源持续集成和持续交付工具,它可以帮助开发人员自动化构建、测试和部署软件。在本攻中,我们将介绍如在Mac上安装Jenkins。 步一:安装Java Jenkins是基于Java开发的,因此安装Jenkins之前,我们需要先安装Java。以下是安装Java的步骤: 打开终端应用程序。 2.行命令来安Ja…

    other 2023年5月9日
    00
  • Android activity堆栈及管理实例详解

    Android Activity堆栈及管理实例详解 在Android开发中,Activity是应用程序的基本组件之一,用于展示用户界面和处理用户交互。Activity堆栈是指存储Activity实例的一种数据结构,用于管理Activity的生命周期和导航。 Activity堆栈的工作原理 Activity堆栈采用后进先出(LIFO)的原则,即最后一个进入堆栈…

    other 2023年8月26日
    00
  • mojo插件demo

    Mojo插件Demo Mojo是一个现代化的Perl Web框架,它提供了一种简单、灵活、高效的方式来构建Web应用程序。Mojo插件是Mojo框架的一个要组成部分,它可以扩展Mojo框架的功能,使得开发者可以更加方便地构建Web应用程序。本文将详细讲解如何编写一个Mojo插件,并提供两个示例说明。 编写Mojo插件 编写Mojo插件的步骤如下: 创建一个M…

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