Java实现单链表的操作

Java实现单链表的操作攻略

单链表是一种常见的数据结构,它由节点构成,每个节点都包含了一个值和指向下一个节点的指针。本文将详细讲解如何在Java中实现单链表的操作。

节点类的定义

我们先定义一个节点类,包含了一个值和一个指向下一个节点的指针。在Java中可以使用类来实现节点:

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

其中val表示节点存储的值,next表示指向下一个节点的指针。

链表的基本操作

插入节点

在单链表中,我们可以在表头或表尾插入节点,也可以在中间插入节点。下面是三种插入节点的方法。

在表头插入节点

在链表的表头插入节点,只需要将新节点的next指向原来的头结点,然后将新节点设置为新的头结点即可。

public ListNode insertAtHead(ListNode head, int val) {
    ListNode newHead = new ListNode(val);
    newHead.next = head;
    return newHead;
}

在表尾插入节点

在链表的表尾插入节点,需要找到链表的尾节点,然后将尾节点的next指向新节点。

public ListNode insertAtTail(ListNode head, int val) {
    ListNode newTail = new ListNode(val);
    if (head == null) { // 链表为空
        return newTail;
    }
    ListNode tail = head;
    while (tail.next != null) { // 找到尾节点
        tail = tail.next;
    }
    tail.next = newTail; // 将尾节点的next指向新节点
    return head;
}

在中间插入节点

在链表的中间插入节点,需要找到需要插入的位置,然后将新节点的next指向该位置的后继节点,然后将该位置的前驱节点的next指向新节点。

public ListNode insertAtIndex(ListNode head, int index, int val) {
    if (index < 0) { // 无效的插入位置
        return head;
    }
    if (index == 0) { // 插入位置为表头
        return insertAtHead(head, val);
    }
    ListNode newNode = new ListNode(val);
    ListNode prev = head;
    for (int i = 0; i < index - 1; i++) { // 找到插入位置的前驱节点
        if (prev == null) {
            return head;
        }
        prev = prev.next;
    }
    if (prev == null) { // 无效的插入位置
        return head;
    }
    newNode.next = prev.next; // 将新节点的next指向后继节点
    prev.next = newNode; // 将前驱节点的next指向新节点
    return head;
}

删除节点

在单链表中,我们可以删除表头节点、表尾节点,也可以删除中间的节点。下面是三种删除节点的方法。

删除表头节点

在链表的表头删除节点,只需要将头结点的next设置为新的头结点即可。

public ListNode deleteAtHead(ListNode head) {
    if (head == null) { // 链表为空
        return null;
    }
    return head.next;
}

删除表尾节点

在链表的表尾删除节点,需要找到链表的尾节点的前驱节点,然后将前驱节点的next指向null

public ListNode deleteAtTail(ListNode head) {
    if (head == null) { // 链表为空
        return null;
    }
    ListNode tail = head;
    ListNode prev = null;
    while (tail.next != null) { // 找到尾节点和前驱节点
        prev = tail;
        tail = tail.next;
    }
    if (prev == null) { // 链表只有一个节点
        return null;
    }
    prev.next = null; // 将前驱节点的next指向null
    return head;
}

删除中间节点

在链表的中间删除节点,需要找到需要删除的节点的前驱节点,然后将前驱节点的next指向需要删除的节点的后继节点。

public ListNode deleteAtIndex(ListNode head, int index) {
    if (index < 0) { // 无效的删除位置
        return head;
    }
    if (index == 0) { // 删除位置为表头
        return deleteAtHead(head);
    }
    ListNode prev = head;
    for (int i = 0; i < index - 1; i++) { // 找到删除位置的前驱节点
        if (prev == null || prev.next == null) {
            return head;
        }
        prev = prev.next;
    }
    if (prev == null || prev.next == null) { // 无效的删除位置
        return head;
    }
    prev.next = prev.next.next; // 将前驱节点的next指向后继节点
    return head;
}

遍历链表

遍历链表可以使用循环或递归的方式,下面是两种遍历链表的方法。

循环遍历链表

循环遍历链表,只需要从头结点开始,依次遍历每一个节点即可。

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

递归遍历链表

递归遍历链表,只需要遍历当前节点和当前节点的后继节点即可。

public void traverse(ListNode head) {
    if (head == null) {
        return;
    }
    System.out.print(head.val + " ");
    traverse(head.next);
}

示例说明

示例1:在链表中插入节点

下面是一个示例,向一个长度为3的链表中插入一个值为5的节点。

ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
Solution solution = new Solution();
head = solution.insertAtIndex(head, 1, 5);
solution.traverse(head); // 输出1 5 2 3

我们先创建一个长度为3的链表,然后使用insertAtIndex方法在第1个位置插入值为5的节点,然后使用traverse方法遍历链表,输出链表中每个节点的值。

示例2:从链表中删除节点

下面是一个示例,从一个长度为3的链表中删除一个值为2的节点。

ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
Solution solution = new Solution();
head = solution.deleteAtIndex(head, 1);
solution.traverse(head); // 输出1 3

我们先创建一个长度为3的链表,然后使用deleteAtIndex方法删除第1个位置的节点,值为2,然后使用traverse方法遍历链表,输出链表中每个节点的值。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现单链表的操作 - Python技术站

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

相关文章

  • 基于Vue制作组织架构树组件

    什么是组织架构树组件?组织架构树组件是一种常见的前端组件,用于显示企业或组织机构的人员层级关系,可以让用户清晰地了解整个组织的人员关系、职位层级等信息。 Vue是什么?Vue是一款轻量级的JavaScript框架,被广泛用于开发Web应用程序。Vue具有极高的灵活性和可定制性,允许开发人员轻松构建复杂的Web组件并实现数据双向绑定和响应式UI设计。 制作组织…

    other 2023年6月27日
    00
  • localforage——轻松实现web离线存储

    localforage——轻松实现web离线存储 简介 localforage是一个简单易用的JavaScript库,用于在Web应用程序中实现离线存储。它提供了一个简单的API,可以轻松地将数据存储在浏览器中,而无需担心浏览器的兼容性问题。 安装和引入 可以使用以下命令来安装localforage: npm install localforage –sa…

    other 2023年5月7日
    00
  • Linux文件目录结构(小白版)

    下面是关于“Linux文件目录结构(小白版)”的详细攻略: 目录 常用目录 目录树结构 其他目录 常用目录 Linux系统中有很多目录,这里列出一些常用的目录: / 根目录:Linux系统的根目录,所有目录和文件都在该目录下。 /bin 目录:系统命令(可执行文件)所在目录,如 ls、cp、mv 命令等。 /dev 目录:设备文件所在目录,Linux系统中一…

    other 2023年6月27日
    00
  • sqlserver中row_number

    以下是关于“SQL Server中ROW_NUMBER函数”的完整攻略,包括基本知识和两个示例。 基本知识 ROW_NUMBER()是SQL Server中的一个窗口函数,用于为结果集中的每一行分配一个唯一的数字。它可以用于排序、分组和筛选数据。 ROW_NUMBER()函数的语法如下: ROW_NUMBER() OVER (ORDER BY column1…

    other 2023年5月7日
    00
  • java TreeUtil菜单递归工具类

    TreeUtil是一个Java工具类,它提供了一些递归函数,用于将列表数据构建成树形结构。这个工具类的使用非常方便,特别是在前后端分离的Web应用程序中,前端通常需要树形结构的JSON数据表示,而该工具类正是为此而设计。 TreeUtil菜单递归工具类的主要功能是将一组菜单数据转换为树结构,并使用json返回给前端页面。 标题 引入 在使用该工具类之前,需要…

    other 2023年6月27日
    00
  • 编码自动识别工具uchardet

    以下是关于“编码自动识别工具uchardet”的完整攻略: uchardet简介 uchardet是一个开源的编码自动识别工具,可以自动识别文本文件编码格式。它支持多种编码格式,包括UTF-8、GBK、GB2312、ISO-8859等。 安装uchardet 在Linux系统中可以使用以下命令安装uchardet: sudo apt-get install …

    other 2023年5月9日
    00
  • php+Ajax无刷新验证用户名操作实例详解

    PHP+Ajax无刷新验证用户名操作实例详解 在网站开发中,常常需要验证用户名是否可用,一般的做法是提交表单后在服务器端进行验证,再返回结果给前端页面。但这种方式会引起页面的刷新,体验不够友好。本文将介绍使用PHP+Ajax技术实现无刷新验证用户名的方法。 实现原理 使用Ajax技术,监听用户名文本框的键入事件,将文本框中的内容发送到服务器端进行验证。服务器…

    other 2023年6月27日
    00
  • elasticsearch-es查询以匹配数组中的所有元素

    以下是关于“Elasticsearch-ES查询以匹配数组中的所有元素”的完整攻略,包括ES查询的定义、匹配数组中的所有元素的查询方法、示例说明和注意事项。 ES查询的定义 Elasticsearch是一个开源的分布式搜索引擎,可以用于全文搜索、结构化搜索和分析等。ES提供了一组查询API,可以用于查询索引中的文档。 匹配数组中的所有元素的查询方法 在ES中…

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