java链表——LinkList详解

news2024/12/23 23:33:00

LinkList详解

:在学习LinkList之前可以先去看一下我的另一篇博客单链表的定义及其模拟实现——java https://editor.csdn.net/md/?articleId=130642627,有助于本博客的理解

ArrayList和LinkedList的区别

在这里插入图片描述

LinkList模拟实现

在这里插入图片描述
定义三个类:MyLinkList用于LinkList成员变量和成员方法的定义、Test用于测试、ListIndexOutException用于定义越界异常

ListIndexOutException类

public class ListIndexOutOfException extends RuntimeException {
    public ListIndexOutOfException() {
    }
}

MyLinkList类

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

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

    //头结点
    public ListNode head;
    //尾结点
    public ListNode last;

    //头插法
    public void addFirst(int data) {
        ListNode node = new ListNode(data);

        if (head == null) {
            head = node;
            last = node;
        } else {
            node.next = head;
            head.prev = node;
            head = node;
        }

    }

    //尾插法
    public void addLast(int data) {
        ListNode node = new ListNode(data);
        if (head == null) {
            last = node;
            head = node;
        } else {
            last.next = node;
            node.prev = last;
            last = last.next;
        }

    }

    //返回某个下标的结点
    public ListNode findIndex(int index) {
        ListNode cur = head;
        while (index != 0) {
            cur = cur.next;
            index--;
        }
        return cur;
    }

    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index, int data) {
        if (index < 0 || index > this.size()) {
            throw new ListIndexOutOfException();
        }
        if (index == 0) {
            addFirst(data);
            return;
        }
        if (index == size()) {
            addLast(data);
            return;
        }
        ListNode node = new ListNode(data);
        ListNode cur = findIndex(index);
        cur.prev.next = node;
        node.prev = cur.prev;
        node.next = cur;
        cur.prev = node;
    }

    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key) {
        ListNode cur = this.head;
        while (cur != null) {
            if (cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    //删除第一次出现关键字为key的节点
    public void remove(int key) {
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                if (cur == head) {
                    head = head.next;
                    return;
                }
                cur.prev.next = cur.next;
                if (cur == last) {
                    last = last.prev;
                    return;
                }
                cur.next.prev = cur.prev;
                return;
            }
            cur = cur.next;
        }
    }

    //删除所有值为key的节点
    public void removeAllKey(int key) {
        ListNode tmp = head;
        while (tmp != null) {
            remove(key);
            tmp = tmp.next;
        }

    }

    //得到单链表的长度
    public int size() {
        ListNode cur = this.head;
        int length = 0;
        while (cur != null) {
            cur = cur.next;
            length++;
        }
        return length;
    }

    //遍历打印
    public void display() {
        ListNode cur = this.head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    public void clear() {
        ListNode cur = head;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.prev = null;
            cur.next = null;
            cur = curNext;
        }
        head = null;
        last = null;
    }
}

Test类

public class Test {
    public static void main(String[] args) {
        //尾插法测试
        MyLinkList myLinkList2 = new MyLinkList();
        myLinkList2.addLast(1);
        myLinkList2.addLast(2);
        myLinkList2.addLast(3);
        myLinkList2.addLast(4);
        myLinkList2.display();

        //头插法测试
        MyLinkList myLinkList1 = new MyLinkList();
        myLinkList1.addFirst(1);
        myLinkList1.addFirst(2);
        myLinkList1.addFirst(3);
        myLinkList1.addFirst(4);
        myLinkList1.display();

        //addIndex测试
        System.out.println("addIndex测试");
        myLinkList1.addIndex(0, 5);
        myLinkList1.display();
        myLinkList1.addIndex(5, 0);
        myLinkList1.display();
        myLinkList1.addIndex(3, 99);
        myLinkList1.display();

        //remove测试
        System.out.println("remove测试");
        myLinkList1.remove(5);
        myLinkList1.display();
        myLinkList1.remove(0);
        myLinkList1.display();
        myLinkList1.remove(99);
        myLinkList1.display();

        //emoveAllKey测试
        System.out.println("removeAllKey测试");
        myLinkList1.addFirst(4);
        myLinkList1.addLast(1);
        myLinkList1.addIndex(1, 2);
        myLinkList1.display();
        myLinkList1.removeAllKey(4);
        myLinkList1.display();
        myLinkList1.removeAllKey(1);
        myLinkList1.display();
        myLinkList1.removeAllKey(2);
        myLinkList1.display();
    }
}

测试结果

在这里插入图片描述

java原生LinkedList详解

实际上在IDEA,JDK环境下的LinkList底层就是一个双向链表,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
在这里插入图片描述在集合框架中,LinkedList也实现了List接口
在这里插入图片描述

原生的LinkedList的继承和实现接口如下
在这里插入图片描述

LinkedList的特点

  1. LinkedList实现了List接口
  2. LinkedList的底层使用了双向链表
  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
  5. LinkedList比较适合任意位置插入的场景

LinkList的使用

构造函数

 public LinkedList() {
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param  c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

无参构造函数没有什么需要说明的.
重点看public LinkedList(Collection<? extends E> c)这个有参的构造函数
先来解释一下这句代码 首先这个构造方法的形参整体的类型是一个Collection<? extends E>类型,形参名是c。Collection<? extends E>类型表明该类型必须是实现了Collection(可以理解为集合的意思)接口的一个类(换句话说就是这个类必须是一个集合),所以从下图中可以得知ArrayList、LinkedList、Vetor等都是可以的。
在这里插入图片描述此外,<? extends E>表明这个集合里面的元素类型是一个泛型,比如是String、Integer、Float等,而且这个泛型是E类型或者E的子类都是可以的,比如可以为Integer,也可以是int。?是通配符。
而整个带参数的构造函数的作用就是将集合c中的所有?类型的元素复制一份作为新的LinkedList类型集合的元素

实例

import java.util.ArrayList;
import java.util.LinkedList;
public class main {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("hello");
        System.out.println(arrayList);
        LinkedList<String>  linkedList = new LinkedList<String>(arrayList);//arrList实现了Conection接口,并且泛型为String ,符合是String或者String子类的要求,而这个带参数的构造函数的作用就将arraylist里面的的元素内容全部复制到linkedList里面来,创建一个新的linkedList对象
        linkedList.add("bai xian");
        System.out.println(linkedList);
        LinkedList<String> linkedList1 = new LinkedList<>(linkedList);
        System.out.println(linkedList1);
    }
}

在这里插入图片描述

public class main {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("hello");
        System.out.println(arrayList);
        LinkedList<Integer>  linkedList = new LinkedList<Integer>(arrayList);//这样就报错了。因为String不是Integer的子类
    }
}

在这里插入图片描述

LinkedList的其他常用方法介绍

在这里插入图片描述
就不一一列举了,有兴趣的可以去看我的另一篇博客LinkList的模拟实现,那里面模拟实现了上述的所有方法。这里给个实例。

实例

public class main {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1); // add(elem): 表示尾插
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        System.out.println(list.size());
        System.out.println(list);
// 在起始位置插入0
        list.add(0, 0); // add(index, elem): 在index位置插入元素elem
        System.out.println(list);
        list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()
        list.removeFirst(); // removeFirst(): 删除第一个元素
        list.removeLast(); // removeLast(): 删除最后元素
        list.remove(1); // remove(index): 删除index位置的元素
        System.out.println(list);
// contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回false
        if(!list.contains(1)){
            list.add(0, 1);
        }

        list.add(1);
        System.out.println(list);
        System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置,返回下标
        System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置。返回下标
        int elem = list.get(0); // get(index): 获取指定位置元素
        list.set(0, 100); // set(index, elem): 将index位置的元素设置为elem
        System.out.println(list);
// subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回
        List<Integer> copy = list.subList(0, 3);
        System.out.println(list);
        System.out.println(copy);
        list.clear(); // 将list中元素清空
        System.out.println(list.size());
    }
}

在这里插入图片描述

LinkedList的遍历

LinkList遍历主要有三种方式,一种是用for—each遍历,一种最常见的用while循环遍历,还有一种使用跌迭代器遍历

实例

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
public class main {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1); // add(elem): 表示尾插
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        System.out.println(list.size());
// foreach遍历
        for (int e:list) {
            System.out.print(e + " ");
        }
        System.out.println();
// 使用迭代器遍历---正向遍历
        ListIterator <Integer> it = list.listIterator();
        while(it.hasNext()){
            System.out.print(it.next()+ " ");
        }
        System.out.println();
// 使用反向迭代器---反向遍历
        ListIterator<Integer> rit = list.listIterator(list.size());
        while (rit.hasPrevious()){
            System.out.print(rit.previous() +" ");
        }
        System.out.println();
    }
}

在这里插入图片描述
至此LinkList的学习就告一段落了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/567180.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据中台建设浪费,数据分析系统如何设计,听听 Gartner 怎么说

2023 年数据分析趋势&#xff1a;数据即业务、从平台到生态、以人为中心 作者 | 宋慧 出品 | CSDN 云计算 数据的价值被越来越多的行业用户看到。不过各种数据系统百花齐放&#xff0c;前几年关于数据中台的讨论仍然众说纷纭。国际研究机构 Gartner 持续对数据分析市场做了调研…

动态规划-数位DP

数字游戏 题目 链接&#xff1a;https://www.acwing.com/problem/content/1084/ 科协里最近很流行数字游戏。 某人命名了一种不降数&#xff0c;这种数字必须满足从左到右各位数字呈非下降关系&#xff0c;如 123 123 123&#xff0c; 446 446 446。 现在大家决定玩一个游…

杂记阅读(三)

目录 校徽和校训 权杖 学术竞赛与荣誉 香港罗德学人 中国大陆罗德学者 富布赖特项目 海外 学友 本土发展 海外扩展 史匹爾財富管理調查 880年&#xff0c;悉尼大学获得了一笔可观的捐赠。富商和慈善家约翰亨利查雷斯在遗嘱中将他的大部分遗产赠予悉尼大学。经过身为…

JavaScript WebAPI 实战

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 本篇文章为大家带来JavaScript WebAPI的使用&#xff0c;请各位过目~~ 目录 文章目录 一、什么是JavaScript WebAPI 1.1 什么是DOM 二、常用的DOM API 2.1 获取元素 2.2 什么是事件 2.2.1 …

Hive数据分层有哪些优点?具体每一层含义是什么?

为什么要分层? 作为一名数据的规划者&#xff0c;我们肯定希望自己的数据能够有秩序地流转&#xff0c;数据的整个生命周期能够清晰明确被设计者和使用者感知到。直观来讲就是如图这般层次清晰、依赖关系直观。 但是&#xff0c;大多数情况下&#xff0c;我们完成的数据体系却…

深度学习基础知识-误差反向传播+训练技巧(无代码仅用来理解)

参考书籍&#xff1a;&#xff08;找不到资源可以后台私信我&#xff09; 《深度学习入门&#xff1a;基于Python的理论与实现 (斋藤康毅)》 《Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow, 2nd Edition (Aurelien Geron [Gron, Aurlien])》 神经网络…

Delphi日薄西山?不仅用户300万,还大佬无数,转身就风靡全球

主人公名叫David Vacanti&#xff0c;是Delphi的长期开发人员&#xff0c;已有接近30年以上的编程经验。 我之所以注意到他&#xff0c;一是因为Delphi属实一波回忆杀。 二是不可思议&#xff1a;他在1983年&#xff0c;便开启了自己的副业。 开了一家叫做“Vacanti Yacht D…

成功加冕!用友大易获评2023最佳招聘管理软件供应商

人力资源服务业旗帜性商业奖项2023金帜奖(HRFLAG AWARDS)颁奖典礼于近日隆重举行。经过3个月的评选&#xff0c;用友大易从615家人力资源服务机构中脱颖而出&#xff0c;最终荣获「2023最佳招聘管理软件供应商」奖项。 2023金帜奖(HRFLAG AWARDS)是人力资源服务行业旗帜性的商业…

STM32cubemx配置驱动DHT11模块

文章目录 前言一、DHT11模块介绍二、DHT11引脚连接及cubemx配置三、DHT11时序分析四、DHT11代码编写总结 前言 本篇文章将带大家学习使用DHT11湿温度模块&#xff0c;使用这个模块可以获取当前的温度和湿度数据。DHT11可以用于智能家居&#xff0c;蔬菜大棚等项目当中适用范围…

SpringBoot+layUI实现表格的某一列数据刷新功能案例分享

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

mysql执行计划explain

mysql 执行计划 explain 介绍 mysql8.0为例&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/explain-output.html EXPLAIN为语句中使用的每个表返回一行信息 SELECT。它按照 MySQL 在处理语句时读取它们的顺序列出输出中的表。这意味着 MySQL 从第一个表中读取一行&…

四维轻云平台常见问题及解决方法

1、在地图中看不见加载的点云或倾斜摄影模型数据&#xff1f; 若点云或模型数据加载后&#xff0c;在地图中看不见&#xff0c;可能是地形的高度高于倾斜模型的高度&#xff0c;导致数据漂浮在空中或者在地形以下&#xff0c;可通过增加数据的移动值Y来调整点云或者模型数据的…

《Java并发编程实战》课程笔记(一)

并发领域的全景图 并发编程的三个核心问题 并发编程可以总结为三个核心问题&#xff1a;分工、同步、互斥。 分工指的是如何高效地拆解任务并分配给线程&#xff1b; Java SDK 并发包里的 Executor、Fork/Join、Future 本质上都是⼀种分工方法。除此之外&#xff0c;并发编程…

吉时利 Keithley 2700数据采集器技术参数

概述&#xff1a; 每个 2700 系列系统均将精密测量、开关和控件集于一个紧凑集成的机箱中&#xff0c;适用于机架安装或台式应用。虽然所有三个系统的核心功能和编程是相同的&#xff0c;但各个主机都具有独特的功能。例如&#xff0c;2701 型具有 10/100BaseTX 以太网接口&am…

【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(5月24日论文合集)

文章目录 一、检测相关(7篇)1.1 Learning Remote Sensing Object Detection with Single Point Supervision1.2 Online Open-set Semi-supervised Object Detection via Semi-supervised Outlier Filtering1.3 Generalizable Synthetic Image Detection via Language-guided Co…

代码随想录训练营Day51| 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费 总结

目录 目录 学习目标 学习内容 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费 学习目标 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费 总结 学习内容 309.最佳买卖股票时机含冷冻期 309. 最佳买卖股票时机含冷冻期 - 力扣&#xff0…

大模型知识Out该怎么办?浙大团队探索大模型参数更新的方法—模型编辑

夕小瑶科技说 原创 作者 | 小戏、Python 大模型在其巨大体量背后蕴藏着一个直观的问题&#xff1a;“大模型应该怎么更新&#xff1f;” 在大模型极其巨大的计算开销下&#xff0c;大模型知识的更新并不是一件简单的“学习任务”&#xff0c;理想情况下&#xff0c;随着世界…

网络协议 — IPSec 安全隧道协议族

目录 文章目录 目录IPSec 安全隧道协议族封装协议Authentication HeaderEncapsulating Security Payload 封装模式传输模式隧道模式 安全偶联协商Security AssociationInternet Key ExchangeIKE 的交换过程 IPSec Virtual Private NetworkIPSec NAT-TTransport 模式Tunnel 模式…

mjpg-streamer框架分析

mjpg-streamer框架分析 文章目录 mjpg-streamer框架分析框架maininput_initinput_runoutput_init 框架 main 这个函数是一个C程序的主函数&#xff0c;接受命令行参数并执行相应的操作。下面是这个函数的要点&#xff1a; 定义了一些变量&#xff0c;包括输入插件数组input、输…

知识点滴 - dBm和mW的转换

分贝毫瓦dBm&#xff0c;decibel-milliwatts&#xff0c;全写为“decibel relative to one milliwatt”&#xff0c;为一个指代功率的绝对值&#xff0c;而不同于dB只是一个相对值。 dBm或dBmW&#xff08;分贝-毫瓦&#xff09;用于表示功率的水平或级别&#xff0c;以分贝&am…