数据结构之链表(LinkedList详解)

2023-11-14

 

文章目录

  • 一、什么是LinkedList?
  • 二、LinkedList的使用
  • 三、LinkedList自实现
  • 四、链表实现逆序打印的两种方式(递归和非递归)
  • 五、ArrayList和LinkedList有什么区别?

一、什么是LinkedList?

LinkedList的底层是 双向链表结构(链表后面介绍),由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
 
在集合框架中,LinkedList也实现了List接口,具体如下:
1. LinkedList实现了 List接口
2. LinkedList的底层使用了 双向链表
3. LinkedList没有实现RandomAccess接口,因此LinkedList 不支持随机访问
4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
 

二、LinkedList的使用

构造方法:

方法 解释
LinkedList()
无参构造
public LinkedList(Collection<? extends E> c)
使用其他集合容器中元素构造List
public static void main(String[] args) { 
  // 构造一个空的LinkedList 
  List<Integer> list1 = new LinkedList<>();
 
  List<String> list2 = new java.util.ArrayList<>(); 
  list2.add("JavaSE");
  list2.add("JavaWeb"); 
  list2.add("JavaEE"); 
  // 使用ArrayList构造LinkedList 
  List<String> list3 = new LinkedList<>(list2); 
}

 LinkedList的常用方法:

方法 解释
boolean add(E e)
尾插 e
void add(int index, E element)
将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c)
尾插 c 中的元素
E remove(int index)
删除 index 位置元素
boolean remove(Object o)
删除遇到的第一个 o
E get(int index)
获取下标 index 位置元素
E set(int index, E element)
将下标 index 位置元素设置为 element
void clear()
清空
boolean contains(Object o)
判断 o 是否在线性表中
int indexOf(Object o)
返回第一个 o 所在下标
int lastIndexOf(Object o)
返回最后一个 o 的下标
List<E> subList(int fromIndex, int toIndex)
截取部分 list

LinkedList的遍历:(foreach遍历、使用迭代器遍历---正向遍历、使用反向迭代器---反向遍历

LinkedList<String> list = new LinkedList<>();
        list.add("javaSE");
        list.add("javaWeb");
        list.add("javaEE");
        // foreach遍历
        for (String x: list) {
            System.out.print(x + " ");
        }
        // 使用迭代器遍历---正向遍历
        ListIterator<String> list1 = list.listIterator();
        while (list1.hasNext()){
            System.out.print(list1.next()+" ");
        }
        // 使用反向迭代器---反向遍历
        ListIterator<String> lis2 = list.listIterator(list.size());
        while (lis2.hasPrevious()){
            System.out.print(lis2.previous()+" ");
        }

三、LinkedList自实现

public class MyLinkedList {
    static class ListNode{
        int val;
        ListNode pre;
        ListNode next;
        public ListNode(int val){
            this.val = val;
        }
    }
    public ListNode head;//头部
    public ListNode tail;//尾部

    public void addFirst(int data){
        ListNode node = new ListNode(data);
        if (head == null){
            head = node;
            tail = node;
            return;
        }
        node.next = head;
        head.pre = node;
        head = node;
    }
    public void addLast(int data){
        ListNode node = new ListNode(data);
        if (head == null){
            head = node;
            tail = node;
            return;
        }
        tail.next = node;
        node.pre = tail;
        tail = node;
    }
    //任意位置插入,第一个数据节点为0号下标
    public boolean addIndex(int index,int data){
        if (index < 0 || index > size()){
            System.out.println("index位置不合法!");
            return false;
        }
        if (index == 0){
            addFirst(data);
            return true;
        }
        if (index == size()){
            addLast(data);
            return true;
        }
        ListNode indexNode = findNode(index);
        ListNode node = new ListNode(data);
        node.pre = indexNode.pre;
        indexNode.pre.next = node;
        node.next = indexNode;
        indexNode.pre = node;
        return true;
    }
    public ListNode findNode(int index){
        ListNode cur = head;
        while (index != 0){
            cur = cur.next;
            index--;
        }
        return cur;
    }
    public boolean contains(int key){
        ListNode cur = head;
        while (cur != null){
            if (cur.val == key)return true;
            cur = cur.next;
        }
        return false;
    }
    public void remove(int key) {
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                if (cur == head) {
                    head = head.next;
                    if (head != null) {
                        head.pre = null;
                    } else {
                        tail = null;
                    }
                } else {
                    cur.pre.next = cur.next;
                    if (cur.next != null) {
                        cur.next.pre = cur.pre;
                    } else {
                        tail = tail.pre;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

    public void removeAllKey(int key) {
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                if (cur == head) {
                    head = head.next;
                    if (head != null) {
                        head.pre = null;
                    } else {
                        tail = null;
                    }
                } else {
                    cur.pre.next = cur.next;
                    if (cur.next != null) {
                        cur.next.pre = cur.pre;
                    } else {
                        tail = tail.pre;
                    }
                }
            }
            cur = cur.next;
        }
    }
    public int size(){
        ListNode cur = head;
        int count = 0;
        while (cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }
    public void display(){
        ListNode cur = head;
        while (cur != null){
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
    }
    public void clear(){
        ListNode cur = head;
        while (cur != null){
            ListNode temp = cur.next;
            cur.next = null;
            cur.pre = null;
            cur = temp;
        }
        head = null;
        tail = null;
    }
}

四、链表实现逆序打印的两种方式(递归和非递归)

递归逆序打印:

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

非递归逆序打印(用栈实现):

public void display(ListNode head) {
        if (head == null) {
            return;
        }
        Stack<ListNode> stack = new Stack<>();
        ListNode cur = head;
        while (cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        while (!stack.empty()) {
            ListNode ret = stack.pop();
            System.out.print(ret.val+" ");
        }
    }

 

五、ArrayList和LinkedList有什么区别?

 

ArrayList实质是顺序表,底层是一个数组。LinkedList实质是一个链表。

他们都具有增删查改的功能,但是在实现方式上有区别。比如在插入元素的时候,ArrayList往0位置上插入一个元素,就需把整个数组整体往后移动,时间复杂度为O(N)。而LinkedList只需要修改指向就可以了,时间复杂度为O(1)。但是ArrayList可以支持随机访问,时间复杂度为O(1),所以一般情况下ArrayList顺序表适合频繁根据下标位置访问,LinkedList比较适合插入和删除比较频繁的情况。

从存储上来说,ArrayList顺序表在物理上和逻辑上都是连续的,但是在扩容的时候,可能会造成空间的浪费。而LinkedList在物理上不一定是连续的,在逻辑上是连续的,可以做到随用随取。

不同点 ArrayList LinkedList
存储空间上         
物理上逻辑上一定连续
逻辑上连续,但物理上不一定连续
随机访问
支持O(1)
不支持:O(N)
头插
需要搬移元素,效率低O(N)
只需修改引用的指向,时间复杂度为O(1)
插入
空间不够时需要扩容
没有容量的概念
应用场景
元素高效存储+频繁访问
任意位置插入和删除频繁

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构之链表(LinkedList详解) 的相关文章

  • 在 Java 中捕获(捕获)窗口中的鼠标光标

    我正在寻找一种方法 在鼠标进入窗口后捕获或捕获该窗口中的鼠标 就像鼠标被捕获在虚拟机窗口中一样 直到用户按 CTRL ALT DEL 或以其他方式释放鼠标 我如何在 Java 中实现这一点 全屏显示不是一个选择 EDIT 这里有一些 SSC
  • 使用 java 删除 XML 根的子级

    这是我的 xml 文件
  • Java Swing BoxLayout 忽略 AlignmentX

    在下面的代码中 通过调用setAlignmentX with Component LEFT ALIGNMENT我希望在居中的滑块上获得左对齐的标签 由于某种原因 标签也居中 似乎与传递给 setAlignmentX 的值无关 我必须向 se
  • 无论线程如何,对象是否总是能看到其最新的内部状态?

    假设我有一个带有简单整数计数变量的可运行对象 每次可运行对象运行时该变量都会递增 该对象的一个 实例被提交以在计划的执行程序服务中定期运行 class Counter implements Runnable private int coun
  • 垂直 ViewPager 中的动画

    我需要垂直制作这个动画ViewPager https www youtube com watch v wuE 4jjnp3g https www youtube com watch v wuE 4jjnp3g 这是我到目前为止所尝试的 vi
  • Java 小程序在 Mac 上闪烁

    这个问题很奇怪 问题并非在每个平台上都会发生 我在使用 MacOSX 的 Google Chrome 中出现了这种情况 但在 Safari 中却没有出现这种情况 对于使用 Windows 的朋友来说 在 Google Chrome 上运行得
  • 使用 Jena 查询维基数据

    目前 Wikidata 有一个 SPARQL 端点 https query wikidata org https query wikidata org 我想使用 Jena 3 0 1 查询此网站 我使用以下代码 但收到错误消息 端点返回的
  • 从 CLI 部署 Maven 项目?

    在 IDE 中构建并运行良好 cd home thufir NetBeansProjects HelloMaven JAVA HOME usr lib jvm java 8 openjdk amd64 home thufir local s
  • 如何让“循环”泛型在 Java 中工作?

    我在编译以下涉及一些泛型的代码时遇到错误 public abstract class State
  • 避免 @Secured 注释的重复值

    我正在尝试使用以下方法来保护我的服务方法 Secured如下 public interface IUserService Secured ROLE ROLE1 ROLE ROLE2 ResponseEntity saveUser Creat
  • 在Java中如何将字节数组转换为十六进制?

    我有一个字节数组 我希望该数组的每个字节字符串转换为其相应的十六进制值 Java中有没有将字节数组转换为十六进制的函数 byte bytes 1 0 1 2 3 StringBuilder sb new StringBuilder for
  • jDBI中如何进行内查询?

    我怎样才能在 jDBI 中执行这样的事情 SqlQuery select id from foo where name in
  • 了解Kafka流groupBy和window

    我无法理解 kafka 流中的 groupBy groupById 和窗口的概念 我的目标是聚合一段时间内 例如 5 秒 的流数据 我的流数据看起来像 value 0 time 1533875665509 value 10 time 153
  • 获取 Future 对象的进度的能力

    参考 java util concurrent 包和 Future 接口 我注意到 除非我弄错了 只有 SwingWorker 实现类才能启动冗长的任务并能够查询进度 这就引出了以下问题 有没有办法在非 GUI 非 Swing 应用程序 映
  • 检查按钮是否可用?如果没有,请等待 5 秒钟,然后再次检查?

    基本上我想看看此刻是否可以单击按钮 如果没有我想再试一次 所以我需要某种 goto 函数来返回到代码的前一行 尽管我怀疑我写得非常糟糕 但它本来可以做得更容易 try driver findElement By xpath button i
  • Firebase:用户注册后如何进行电话号码验证?

    所以我知道我可以使用电子邮件验证或电话号码验证 但我想做的是在用户注册或登录后进行电话号码验证 如何连接这两种身份验证方法 最后 Firebase中是否有一个函数可以检查用户是否通过电话号码验证 谢谢 即使用户已通过身份验证 您仍然可以使用
  • Java 中序列化的目的是什么?

    我读过很多关于序列化的文章 以及它如何如此美好和伟大 但没有一个论点足够令人信服 我想知道是否有人能真正告诉我通过序列化一个类我们真正可以实现什么 让我们先定义序列化 然后我们才能讨论它为什么如此有用 序列化只是将现有对象转换为字节数组 该
  • Java时区混乱

    我正在运行 Tomcat 应用程序 并且需要显示一些时间值 不幸的是 时间快到了 还有一个小时的休息时间 我调查了一下 发现我的默认时区被设置为 sun util calendar ZoneInfo id GMT 08 00 offset
  • 如何在J2ME中获取数字的幂[重复]

    这个问题在这里已经有答案了 可能的重复 J2ME power double double 数学函数实现 https stackoverflow com questions 2076913 j2me powerdouble double ma
  • 如何使用socket.io发送图像文件(二进制数据)?

    我无法从以下位置发送数据Android Client to NodeJS Server I use Socket IO 客户端 https github com socketio socket io client java我的客户端中的ja

随机推荐

  • 华南X99F8D开不了机——主板出现错误码67的解决方案

    华南X99F8D开不了机 主板出现错误码67的解决方案 前言 笔者的双路e5 大数据双路e5主机搭建 2696v3 256g内存 配置 主板 x99f8d CPU e5 2696v3 2 36核72线程 内存条 DDR4 ECC 32G 8
  • 2013 Lost connection to MySQL server at ‘handshake: reading initial communication packet

    Navicat连接mysql报错 尝试重启一下MySQL 有可能就解决了
  • mac出现java程序运行版本不一致

    mac出现java程序运行版本不一致 Burpsuite pro v2022版本 Burpsuite pro v2023 6 2版本 解决方案 Burpsuite pro v2022版本 在安装BurpSuite的时候 执行启动程序 jav
  • 如何在IDEA中隐藏文件或者文件夹

    Setting File Types Ignored Files and Folders 输入要隐藏的文件名 支持 号通配符 回车确认添加 File Setting Editor File Types 中点 然后点击第一个方框 点第二个方框
  • 苹果上架Guideline 4.3 - Design

    最近上架苹果商店 审核提示 Guideline 4 3 Design We noticed your app shares a similar binary metadata and or concept as apps previousl
  • SpringBoot+Vue开发笔记

    参考 https www bilibili com video BV1nV4y1s7ZN p 1 概要总结 1 MVC架构 View 与用户交互 Controller 负责协调分发任务 Model 数据处理 2 Controller与 Re
  • Bootstrap 4:如何使顶部固定的Navbar保持在容器中而不拉伸?

    There are many ways to make a fixed navbar stay inside a parent s div container We ll go over the most straightforward o
  • Demosaic------颜色插值

    光线中主要包含三种颜色信息 即R G B 但是由于像素只能感应光的亮度 不能感应光的颜色 同时为了减小硬件和资源的消耗 必须要使用一个滤光层 使得每个像素点只能感应到一种颜色的光 目前主要应用的滤光层是bayer GRBG格式 如下图所示
  • 【论文阅读】BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

    论文阅读 BERT Pre training of Deep Bidirectional Transformers for Language Understanding 前言 BERT 是 Google 于 2018 年提出的 NLP 预训
  • Cocos Creator 初识编辑器界面

    编辑器界面的介绍 1 资源管理器 2场景编辑器 3层级管理器 4属性检查器 节点和组件属性的工作区 以及脚步绑定位置 5控制库 预设控件的仓库库 可以通过拖拽方式添加到场景中 并且可以将用户自己的预制资源 prefab 添加到控件库里方便再
  • Jetson Nano介绍

    1 bo1公版介绍 Jetson NanoBO1公版的实物图如下图所示 其中1是TF卡接口 可以进行系统镜像烧写 2是40PIN GPIO扩展接口 3是用来传输数据或使用电源供电的Micro USB接口 4是千兆以太网口 5是USB3 0接
  • netstat命令详解

    概述 最近在学网络编程 用到了netstat命令 觉得非常有用 就把netstat的信息整理一下 以备不时之需 Netstat是控制台命令 是一个监控TCP IP网络的非常有用的工具 它可以显示路由表 实际的网络连接以及每一个网络接口设备的
  • L2-033 简单计算器 - java

    L2 033 简单计算器 时间限制 400 ms 内存限制 64 MB 题目描述 本题要求你为初学数据结构的小伙伴设计一款简单的利用堆栈执行的计算器 如上图所示 计算器由两个堆栈组成 一个堆栈 S 1 S 1 S1 存放数字 另一个堆栈
  • 腾讯java运营开发面试题_腾讯运营开发面经

    前言 腾讯面试体验流程非常的正规 不像其他小厂 xjb乱来的 签到 指引 等待 面试 一套下来体验很是不错 而且面试官人也挺好的 面试官搞c 的 我Java 他一个c 的问题都没有问我 很是不错 我说一个不好的事情 我tm迟到了 约的时间是
  • ROS STAGE教程3 (编译源码,自定义Lidar噪声)Ubuntu 18.04 Ubuntu 16.04

    源码地址 https github com rtv Stage git 系统 Ubuntu 18 04 ROS Melodic 噪声生成模块 lasernoise 路径为Stage examples ctrl lasernoise cc i
  • 台式计算机显示连接不可用,电脑莫名其妙无法上网提示“连接不可用”如何解决...

    电脑使用时间久了 会出现各种各样的故障问题 最常见属于网络问题 近期一位用户说电脑莫名其妙无法识别网络 桌面右下角提示 连接不可用 无法上网是一个比较烦人的问题 对于这种情况 可以通过以下几步简单的方法就能解决问题 1 当我们遇到无法识别出
  • Unity 简单游戏编程(1) 开始界面设计

    转自 http blog csdn net qqmcy article details 9330405 using UnityEngine using System Collections public class Script 10 01
  • 斌哥的 Docker 进阶指南

    过去的一年中 关于 Docker 的话题从未断过 而如今 从尝试 Docker 到最终决定使用 Docker 的转化率依然在逐步升高 关于 Docker 的讨论更是有增无减 另一方面 大家的注意力也渐渐从 Docker 是什么 转移到 实践
  • 如何正确控制springboot中bean的加载顺序总结

    1 为什么需要控制加载顺序 springboot遵从约定大于配置的原则 极大程度的解决了配置繁琐的问题 在此基础上 又提供了spi机制 用spring factories可以完成一个小组件的自动装配功能 在一般业务场景 可能你不大关心一个b
  • 数据结构之链表(LinkedList详解)

    文章目录 一 什么是LinkedList 二 LinkedList的使用 三 LinkedList自实现 四 链表实现逆序打印的两种方式 递归和非递归 五 ArrayList和LinkedList有什么区别 一 什么是LinkedList