java代码实现双向链表

yizhihongxing

下面我为大家详细讲解如何使用Java代码实现双向链表。

什么是双向链表?

双向链表是一种数据结构,与单向链表类似,但其每个节点还会连接到其前驱节点。一个节点包括数据域和两个指针域,分别指向前后两个节点。可以看做是两个单向链表的结合体。

双向链表的实现

1. 定义节点类

Java代码中,需要先定义一个节点类来表示链表中的每个节点。Java代码实现如下:

public class ListNode {
    int val;
    ListNode prev;
    ListNode next;

    public ListNode(int val) {
        this.val = val;
        this.prev = null;
        this.next = null;
    }
}

ListNode表示一个节点,包含val表示节点存储的值,prev表示前一个节点,next表示后一个节点。我们使用构造函数来初始化这些值。

2. 实现双向链表类

接下来,实现双向链表类,包含添加节点、删除节点、输出链表等基本操作。Java代码实现如下:

public class DoublyLinkedList {
    private ListNode head;
    private ListNode tail;
    private int size;

    public DoublyLinkedList() {
        this.head = null;
        this.tail = null;
        this.size = 0;
    }

    public void addFirst(int val) {
        ListNode node = new ListNode(val);
        if (head == null) {
            head = tail = node;
        } else {
            node.next = head;
            head.prev = node;
            head = node;
        }
        size++;
    }

    public void addLast(int val) {
        ListNode node = new ListNode(val);
        if (tail == null) {
            head = tail = node;
        } else {
            tail.next = node;
            node.prev = tail;
            tail = node;
        }
        size++;
    }

    public void addAtIndex(int index, int val) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("Invalid index");
        } else if (index == 0) {
            addFirst(val);
        } else if (index == size) {
            addLast(val);
        } else {
            ListNode node = new ListNode(val);
            ListNode cur = getNodeAtIndex(index);
            ListNode prev = cur.prev;
            prev.next = node;
            node.prev = prev;
            node.next = cur;
            cur.prev = node;
            size++;
        }
    }

    public ListNode getNodeAtIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Invalid index");
        }
        ListNode cur = head;
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }
        return cur;
    }

    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException("Invalid index");
        }
        ListNode cur = getNodeAtIndex(index);
        ListNode prev = cur.prev;
        ListNode next = cur.next;
        if (prev == null) {
            head = next;
        } else {
            prev.next = next;
        }
        if (next == null) {
            tail = prev;
        } else {
            next.prev = prev;
        }
        size--;
    }

    public void printList() {
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}

DoublyLinkedList表示双向链表类,包含头指针head、尾指针tail和链表节点个数size,下面介绍一下几个核心方法。

  • addFirst方法:在链表头部添加节点。
  • addLast方法:在链表尾部添加节点。
  • addAtIndex方法:在链表的index位置添加节点,如果index位置越界,则抛出异常。
  • deleteAtIndex方法:删除链表中index位置的节点,如果index位置越界,则抛出异常。
  • getNodeAtIndex方法:获取链表中index位置的节点。
  • printList方法:输出链表中所有节点的值。

这样,我们就实现了一个双向链表类。

3. 示例

下面通过两个示例说明如何使用我们刚刚实现的双向链表。

示例1:在双向链表中添加节点

public static void main(String[] args) {
    DoublyLinkedList list = new DoublyLinkedList();
    list.addFirst(1);
    list.addLast(3);
    list.addAtIndex(1, 2);
    list.printList();
    // 输出结果:1 2 3
}

在示例中,首先创建了一个双向链表对象list,然后在链表头部添加节点1,接着在链表尾部添加节点3,最后在链表的第二个位置插入节点2,然后输出完整的链表节点值。

示例2:在双向链表中删除节点

public static void main(String[] args) {
    DoublyLinkedList list = new DoublyLinkedList();
    list.addFirst(1);
    list.addLast(2);
    list.addLast(3);
    list.deleteAtIndex(1);
    list.printList();
    // 输出结果:1 3
}

在示例中,首先创建了一个双向链表对象list,然后在链表头部添加节点1,接着在链表尾部添加节点2和节点3,之后删除了第二个节点,并输出完整的链表节点值。

总结

以上就是Java代码实现双向链表的完整攻略了。双向链表和单向链表主要区别在于节点除了保存指向下一个节点的指针外,还保存指向上一个节点的指针。通过使用Java代码,我们可以轻松地创建和操作双向链表,实现常见的链表操作,如添加节点、删除节点等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java代码实现双向链表 - Python技术站

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

相关文章

  • 一文吃透Hilt自定义与跨壁垒

    一文吃透Hilt自定义与跨壁垒 介绍 Hilt是一个基于Dagger的依赖注入框架。它可以帮助开发者更轻松地管理依赖注入和依赖关系,是Android中最流行的依赖注入框架之一。 本文将详细介绍Hilt的自定义和跨壁垒功能,并提供两个示例。 自定义 Hilt提供了许多自定义功能,可以根据应用程序的需求进行配置。 组件绑定 组件绑定是Hilt中最基本的自定义功能…

    other 2023年6月25日
    00
  • 解决ajax跨域请求(总结)

    解决ajax跨域请求(总结) 在前端开发中,我们经常会遇到这样的问题:当我们的网站想从其它域名的服务器上获取数据时,由于同源策略的限制,我们经常会遇到跨域请求失败的情况。如何解决这个问题呢?本篇文章旨在总结各种解决跨域请求的方法,希望能够帮助到开发者。 什么是跨域请求 同源策略(Same-origin policy)是浏览器的一种安全策略。它指的是,不同域名…

    其他 2023年3月28日
    00
  • ffmpeg批量转吗

    ffmpeg批量转码 在日常的视频处理和编辑过程中,我们经常需要将一些视频文件转换成特定的格式或者特定的参数,以满足特定的需求。常见的转换工具之一就是FFmpeg。这个工具本身提供了很多命令行选项,可以进行转码、剪辑、过滤等操作。但是,如果我们需要对很多视频文件进行相同的操作,手工一个一个进行命令行处理就非常繁琐费时。本文将介绍如何使用FFmpeg进行批量转…

    其他 2023年3月28日
    00
  • Debian或Ubuntu系统启动后进入命令行界面的教程

    这里给出Debian和Ubuntu系统启动后进入命令行界面的完整攻略: 1. 从GUI界面进入命令行界面 首先,在系统运行GUI的环境下,按下Ctrl+Alt+T组合键,打开一个终端窗口。 在终端窗口中输入命令sudo systemctl stop gdm(对于GDM桌面环境,如果使用其他桌面环境则需要相应修改命令),停止GUI桌面环境。 界面会黑屏并提示输…

    other 2023年6月27日
    00
  • element-ui中如何给el-table的某一行或某一列加样式

    当使用element-ui的el-table组件时,可以通过以下两种方式给某一行或某一列加样式: 使用slot-scope自定义列模板,并添加对应的样式类: <template> <el-table :data="tableData"> <el-table-column prop="name&quo…

    other 2023年6月28日
    00
  • vivoX70开发者选项在哪里打开?vivoX70进入开发者模式的方法

    以下是“vivo X70开发者选项在哪里打开?vivo X70进入开发者模式的方法”的完整攻略,过程中包含两个示例说明。 一、什么是vivo X70的开发者选项? vivo X70的开发者选项是一组隐藏设置,用于给开发者提供更高级的调试和定制功能。用户可以根据需要自定义开发者选项。例如,开发者选项中允许用户开启USB调试模式、调节动画速度、更改分辨率,使其更…

    other 2023年6月26日
    00
  • linux下解压war格式的包

    以下是Linux下解压war格式的包的完整攻略,包括以下内容: 概述 解压war格式的包的基本用法 示例说明 1. 概述 在Linux系统中,war格式的包是一种常见的Java Web应用程序打包格式。解压war格式的包可以查看其中的文件和目录结构,也可以修改其中的文件。本文将介绍如何在Linux系统中解压war格式的包。 2. 解压war格式的包的基本用法…

    other 2023年5月9日
    00
  • 详解小程序如何改变onLoad的执行时机

    首先需要了解小程序的生命周期,onLoad是在页面加载时执行的函数,而且是在onShow之前执行。在页面初始化时,onLoad只会执行一次,此后通过页面跳转时,如果页面还在缓存中,则不会再次执行onLoad函数。 想要改变onLoad的执行时机,需要在页面的options中添加isReload参数,通过判断isReload参数的值来决定是否需要重新加载页面。…

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