zoukankan      html  css  js  c++  java
  • 3.5链表----链表中元素的删除(只删除一个元素情况)

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

    一、图示删除逻辑

    假设我们需要在链表中删除索引为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

  • 相关阅读:
    环境是如何建立的 启动文件有什么
    环境中存储的是什么
    串行 并行 异步 同步
    TPC-H is a Decision Support Benchmark
    进程通信类型 管道是Linux支持的最初Unix IPC形式之一 命名管道 匿名管道
    删除环境变量
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
  • 原文地址:https://www.cnblogs.com/wfaceboss/p/10642754.html
Copyright © 2011-2022 走看看