Java链表中元素删除的实现方法详解【只删除一个元素情况】

本文实例讲述了Java链表中元素删除的实现方法。分享给大家供大家参考,具体如下:

该部分与上一节是息息相关的,关于如何在链表中删除元素,我们一步一步来分析:

一、图示删除逻辑

假设我们需要在链表中删除索引为2位置的元素,此时链表结构为:

若要删除索引为2位置的元素,需要获取索引为2位置的元素之前的前置节点(此时为索引为1的位置的元素),因此我们需要设计一个变量prev来记录前置节点。

1.初始时变量prev指向虚拟头结点dummyHead:

2.寻找到前置节点位置,(对于该例子前置节点为索引为1的位置的元素)。

则此时prev记录的next即为需要删除的节点,记为delNode变量。

3.删除操作

第一步:将prev的next指向delNode的next,如图:

代码为:

prev.next=delNode.next;

第二步:为了java能够回收这个被删除的空间,我们手动让需要被删除的节点从链表中脱离开来,也就是delNode的next变为null。

代码为:

delNode.next=null;

二、代码实现删除逻辑

2.1 从链表删除第index(0-based)个位置的元素 ,返回删除的元素

首先,初始化当前前置节点指向虚拟头结点,然后遍历寻找到需要被删除节点的前置节点,最后执行删除逻辑。

//从链表删除第index(0-based)个位置的元素 ,返回删除的元素 (实际不常用,练习用)
  public E remove(int index) {
    if (index < 0 || index >= size) {
      throw new IllegalArgumentException("remove failed,Illegal index");
    }

    //获取虚拟头节点
    Node<E> prev = dummyHead;
    for (int i = 0; i < index; i++) {
      //获取到删除元素之前节点
      prev = prev.next;
    }

    Node<E> retNode = prev.next;//被删除的元素
    prev.next = retNode.next;
    retNode.next = null;
    size--;

    return retNode.e;
  }

2.2 从链表中删除第一个元素,返回删除的元素

基于remove(int index)方法实现该方法:

//从链表中删除第一个元素,返回删除的元素
  public E removeFirst() {
    return remove(0);
  }

2.3 从链表中删除最后一个元素,返回删除的元素

基于remove(int index)方法实现该方法:

//从链表中删除最后一个元素,返回删除的元素
  public E removeLast() {
    return remove(size - 1);
  }

三、测试删除逻辑

基于上一节的测试代码,我们新增删除逻辑代码,此时贴出全部测试代码:

package LinkedList;

public class TestMain {
  public static void main(String[] args) {
    LinkedList<Integer> linkedList = new LinkedList<Integer>();

    System.out.println("============在链表头部添加============");
    for (int i = 0; i < 5; i++) {
      linkedList.addFirst(i);
      System.out.println(linkedList);
    }

    System.out.println("============修改链表============");
    linkedList.set(2, 666);
    System.out.println(linkedList);

    System.out.println("============删除链表中666节点============");
    linkedList.remove(2);
    System.out.println(linkedList);
  }
}

结果为:

四、链表的时间复杂度分析

4.1 添加操作的时间复杂度

(1)在链表尾部添加(addLast())需要从头遍历,时间复杂度为O(n);

(2)在链表头部添加(addFirst()),时间复杂度为O(1);

(3)在链表任意位置添加(add(int index,E e)),平均情况下为O(n/2)=O(n);

4.2 删除操作的时间复杂度

(1)删除链表最后一个元素(removeLast()),需要遍历找到最后元素的前一个元素,故时间复杂度为O(n);

(2)删除链表的第一个元素(removeFirst()),时间复杂度为O(1)

(3)删除链表中任意位置节点(remove(index)),平均情况下时间复杂度为O(n/2)=O(n);

4.3 修改操作

由于链表不支持随机访问,需要从头开始寻找直到找到需要修改的节点,故时间复杂度为O(n)

4.4 查找操作

由于链表不支持随机访问,需要从头开始寻找直到找到需要的节点,故时间复杂度为O(n)

从上不难看出,关于链表的添加操作、删除操作、修改操作、查找操作的时间复杂度均为O(n),看到这个顿时心凉了半截,这个还搞个mao,还不如数组呢,其实确实是这样的,因为对于数组来说,只要有索引即可实现快速访问。但是对于链表来说,我们如果只对链表头进行添加操作、删除操作、查找操作那么它的的时间复杂度为均O(1),这时和数组是一样,是动态的,不会大量的浪费内存空间,这就是它的优势,由于链表是最基础的动态数据结构,在此基础上将会有更多关于链表的应用。

关于本小节,若您觉得还行、还过得去,麻烦给个推荐吧,谢谢!!

关于链表的源码 https://github.com/FelixBin/dataStructure/tree/master/src/LinkedList

更多关于java算法相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。

(0)

相关推荐

  • 如何实现java递归 处理权限管理菜单树或分类

    这篇文章主要介绍了如何实现java递归 处理权限管理菜单树或分类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.数据库表设计 2.实体类设计 package com.ieou.capsule.dto.SystemPermissions; import java.util.List; /** * 功能菜单类 */ public class SystemPermissionsTree { private String functionCode;

  • java链表应用--基于链表实现队列详解(尾指针操作)

    本文实例讲述了java基于链表实现队列.分享给大家供大家参考,具体如下: 在开始栈的实现之前,我们再来看看关于链表的只在头部进行的增加.删除.查找操作,时间复杂度均为O(1). 一.链表改进分析 对于队列这种数据结构,需要在线性结构的一端插入元素,另外一端删除元素.因此此时基于链表来实现队列,则有一端的时间复杂度为O(n).因此我们不能使用之前已经实现的链表结构,我们需要改进我们的链表.思路如下: 1.参考在链表头部删除.增加元素的时间复杂度为O(1)的思路,我们在链表的尾部设立一个Node型的

  • java递归算法的实例详解

    递归三要素: 1.明确递归终止条件: 2.给出递归终止时的处理办法: 3.提取重复的逻辑,缩小问题规模. 1.1+2+3+-+n import java.util.Scanner; public class Recursion { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); System.out.println(sum(n)); } publ

  • Java链表中添加元素的原理与实现方法详解

    本文实例讲述了Java链表中添加元素的原理与实现方法.分享给大家供大家参考,具体如下: 1.链表中头节点的引入 1.1基本的链表结构: 1.2对于链表来说,若想访问链表中每个节点则需要把链表的头存起来,假如链表的头节点为head,指向链表中第一个节点,如图: 1.3使用代码表示此时的链表 //定义头节点 private Node head; //节点个数 private int size; //无参数构造函数 public LinkedList() { head = null; size = 0

  • Java方法递归调用实例解析

    这篇文章主要介绍了Java方法递归调用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 /* 关于方法的递归调用 1.什么是递归? -方法自身调用自身 a(){ a(){ } } 2.递归是很耗费栈内存的,递归算法可以不用的时候尽量不用 3.一下程序运行的时候发生了这样一个错误[不是异常,是错误Error]: java.lang.StackOverflowErroe 栈内存溢出错误. 错误放生无法挽回,只有一个结果,就是JVM停止工作 4

  • Java递归运行的机制:递归的微观解读图文分析

    本文讲述了Java递归运行的机制:递归的微观解.分享给大家供大家参考,具体如下: 前言:在java递归基础与递归的宏观语意和java链表的天然递归结构性质中我们分别通过数组以及链表对递归进行了应用,那时我们只是对递归进行了宏观理解--递归是将问题化为更小问题的子过程.这一节我们对在4.1节中递归在数组中的应用和4.2节中递归在链表中的应用进行微观解读: 一.关于4.1节中递归在数组中的应用 1) 我们先来看看4.1节中的代码实现,如下图: 为了更好的进行分析,我们将上述代码的最后一句进行拆分,拆

  • Java实现链表中元素的获取、查询和修改方法详解

    本文实例讲述了Java实现链表中元素的获取.查询和修改方法.分享给大家供大家参考,具体如下: 本节是在上一小节Java链表中添加元素的基础上继续完善我们的链表相关方法的编写,在本节中我们着重对如何获取链表中元素.查询元素以及修改元素进行学习. 一.获取元素 1.关于获取链表中元素的方法的分析 由于我们使用了虚拟头结点,而我们每次都需要从第一个真实节点开始,因此需要首先得到虚拟头结点的下一个节点是谁,然后在此基础上进行遍历工作,相关代码如下: //获取链表的第index(0-based)个位置的元

  • Java递归基础与递归的宏观语意实例分析

    本文实例讲述了Java递归基础与递归的宏观语意.分享给大家供大家参考,具体如下: 1.什么是递归 本质上,将原来的问题,转化为更小的同一问题 2.例子分析 假设我们需要对数组进行求和操作(只是为了更好理解递归程序) 要求如下:求解从索引为0到n-1的数组元素和. 分析: 为了能求解从索引为0到n-1的数组元素和,可以分解为第0个数加上索引从1到n-1的数组元素和,如下: 此时求解索引从1到n-1的数组元素和的规模比求解从索引为0到n-1的数组元素和要少一个数以此类推,如下: ....... 最基

  • Java链表(Linked List)基本原理与实现方法入门示例

    本文实例讲述了Java链表(Linked List)基本原理与实现方法.分享给大家供大家参考,具体如下: 在分析链表之前,我们先来对之前的动态数组.栈.队列总结一下: (1)底层依托于静态数组 (2)依靠resize解决固定容量问题 (3)是一种假的的动态数据结构 1.什么是链表 可以从以下两个部分来理解什么是链表 (1)最简单的动态数据结构,是一种真正的动态数据结构: (2)是一种数据的存储方式,数据存储在"节点"(Node)中 1.1结构基本代码: class Node{ E e;

  • Java链表的天然递归结构性质图文与实例分析

    本文实例分析了Java链表的天然递归结构性质.分享给大家供大家参考,具体如下: 有关链表,参考之前的文章学习. 要求:使用递归删除链表中指定的所有元素值. 一.图文分析 假设有这么一个链表,如下图: 分析:基于链表的宏观语意(递归是问题更小的子过程)进行分析 我们可以把上述链表看成是一个头结点后面挂接了一个更小的链表组成,如下图: 此时我们可以把链表概括成如下的链表结构: 1.在一个头结点+更小的链表基础上,从更小的链表中删除指定元素,得到一个全新的链表--图中红丝的方块. 此时我们需要关心如何

  • Java基于链表实现栈的方法详解

    本文实例讲述了Java基于链表实现栈的方法.分享给大家供大家参考,具体如下: 在上几小节中我们实现了基本的链表结构,并在上一节的底部给出了有关链表的源码,此处在贴一次吧,猛戳 在开始栈的实现之前,我们再来看看关于链表的只在头部进行的增加.删除.查找操作,时间复杂度均为O(1),基于链表的这几个优势,我们在此基础上实现栈. 前言,在写本小节之前,我们已经实现了一个基于静态数组的栈,转到查看.此处我们实现基于链表的栈. 1.链表类拷贝到Stack 包下: 在实现基于静态数组的栈的时候,我们已经新建了

随机推荐