【Java数据结构】LinkedList与链表

认识LinkedList

        LinkedList就是一个链表,它也是实现List接口的一个类。LinkedList就是通过next引用将所有的结点链接起来,所以不需要数组。LinkedList也是以泛型的方法实现的,所以使用这个类都需要实例化对象。

        链表分为很多种,比较常用的就两种:单链表(单向、不带头、非循环)和双链表(双向、不带头、非循环),后面会模拟实现。下面是顺序表和链表的区别:

模拟实现LinkedList

单链表

        首先需要创建结点,但是它比顺序表多了一个next引用,可以通过next引用来访问下一个结点,不再需要通过连续地址访问,首先先创建结点这个类, 然后再实现增删查改等这些方法:

链表长度、遍历链表、头插法、尾插法、任意位置插入、查找关键字key是否在链表中 、删除第一次出现关键字为key的节点、删除所有值为key的节点、清空。

public class MySingle {
    static class ListNode{
        private int val;
        private ListNode next;
         public ListNode(int val){
             this.val = val;
         }
    }
    private ListNode head;
    //头插法
    public void addFirst(int data){
        ListNode node = new ListNode(data);
        node.next = head;
        head = node;
    }
    //尾插法
    public void addLast(int data){
        ListNode node = new ListNode(data);
        if (head == null){
            head = node;
        }else {
            ListNode cur = head;
            while (cur.next != null) {
                cur = cur.next;
            }
            cur.next = node;
        }
    }
    //任意位置插入
    public void addIndex(int index,int data){
        if (index < 0 || index > size()){
            throw new IndexOutOfException("位置不合法!");
        }
        if (index == 0){
            addFirst(data);
            return;
        }
        ListNode node = new ListNode(data);
        ListNode cur = head;
        while (index - 1 != 0){
            cur = cur.next;
            index--;
        }
        //将index位置前后两个节点和新结点联系起来
        node.next = cur.next;
        cur.next = node;
     }
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = head;
        while (cur != null){
            if (cur.val == key){
                return true;
            }
        }
        return false;
    }
    public ListNode keyPre(int key){
        ListNode cur = head;
        while (cur.next != null){
            if (cur.next.val == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }
    //删除第一次出现关键字为key的节点
    public void remove(int key){
        if (head == null){
            return;
        }
        if (head.val == key){
            head = head.next;
            return;
        }
        //找到key结点的前一个结点
        ListNode pre = keyPre(key);
        ListNode del = pre.next;
        pre.next = del.next;
    }
    //删除所有值为key的节点
    public void removeAllKey(int key){
        ListNode pre = head;
        ListNode cur = head.next;
        while (cur != null){
            if (cur.val == key){
                pre.next = cur.next;
                cur = cur.next;
            }else{
                pre = pre.next;
                cur = cur.next;
            }
        }
        if (head.val == key){
            head = head.next;
        }
     }
    //得到单链表的长度
    public int size(){
        int count = 0;
        ListNode cur = head;
        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;
        }
        System.out.println();
    }
}

双链表(LinkedList)

        LinkedList其实就是一个双链表, 它既可以访问前驱又可以访问后继,所以可以快速插入和删除。下面是LinkedList模拟实现,比较难的就是插入和删除:

public class MyLinkedList {
    static class ListNode{
        private int val;
        private ListNode prev;
        private 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;
        }else {
            head.prev = node;
            node.next = head;
            head = node;
        }
    }
    //尾插法
    public void addLast(int data){
        ListNode node = new ListNode(data);
        if (tail == null){
            head = node;
            tail = node;
        }else{
            tail.next = node;
            node.prev = tail;
            tail = node;
            //tail = tail.next;
        }
    }
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        if (index < 0 || index > size()){
            throw new IndexOutofBoundException(index+"位置不合理!");
        }
        ListNode node = new ListNode(data);
        ListNode cur = head;
        while (index > 0){
            cur = cur.next;
            index--;
        }
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;

    }
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = head;
        while (cur != null){
            if (cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
    //删除第一次出现关键字为key的节点
    public void remove(int key){
        if (head == null){
            return ;
        }
        ListNode cur = head;
        while(cur != null ) {
            if (cur.val == key){
                if (cur.next == null && cur.prev == null){
                    head = null;
                    tail = null;
                    return;
                }
                if (cur.prev == null) {
                    head = cur.next;
                    cur.next.prev = null;
                    return;
                }
                if(cur.next == null){
                    tail = cur.prev;
                    cur.prev.next = null;
                    return;
                }
                cur.prev.next = cur.next;
                cur.next.prev = cur.prev;
                return;
            }else{
                cur = cur.next;
            }
        }
    }
    //删除所有值为key的节点
    public void removeAllKey(int key){
        if (head == null){
            return ;
        }
        ListNode cur = head;
        while(cur != null ) {
            if (cur.val == key){
                if (cur.next == null && cur.prev == null){
                    head = null;
                    tail = null;
                }else if (cur.prev == null) {
                    head = cur.next;
                    cur.next.prev = null;
                }else if(cur.next == null){
                    tail = cur.prev;
                    cur.prev.next = null;
                }else {
                    cur.prev.next = cur.next;
                    cur.next.prev = cur.prev;
                }
                cur = cur.next;
            }else{
                cur = cur.next;
            }
        }
    }
    //得到单链表的长度
    public int size(){
        ListNode cur = head;
        int size = 0;
        while (cur != null){
            size++;
            cur = cur.next;
        }
        return size;
    }
    //清空
    public void clear(){
        ListNode cur = head;
        while(cur != null){
            ListNode curNext = cur.next;
            cur.prev = null;
            cur.next = null;
            cur = curNext;
        }
        head = null;
        tail = null;
    }
    //遍历
    public void display(){
        ListNode cur = head;
        while (cur != null){
            System.out.print(cur.val+"   ");
            cur = cur.next;
        }
        System.out.println();
    }
}

LinkedList的创建

构造一个对象,可以无参构造(较为常用,在其里初始化一个数组)。 

LinkedList的遍历

        遍历的方法和ArrayList里一样,三种:for循环、增强for循环、迭代器。这两个遍历方法都是一样的,就不重复叙述。https://blog.csdn.net/2402_84815218/article/details/144038207?spm=1001.2014.3001.5502

LinkedList常用方法

 这些方法和ArrayList中的方法差不多都一样,只是实现的过程不一样。这里我就举几个例子:

    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(12);//尾插进入
        list.add(23);
        System.out.println(list);//【12,23】
//        list.add(3, 100);//插入到第index位置,但是该list中没有第三个位置
//        System.out.println(list);
        System.out.println(list.get(1));//得到1位置元素  23
        list.set(1,100);//更新1位置的元素
        System.out.println(list.get(1));// 100
        list.remove(1);//删除1位置元素
        list.clear();//清空链表
        System.out.println(list);//【】
    }

ArrayList与LinkedList的区别

        简而言之就是LinkedList的插入和删除的复杂度高,而ArrayList的可能需要移动n次数据,所以应用根据应用场景来判断使用哪一种。         

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从0入门自主空中机器人-2-2【无人机硬件选型-PX4篇】

1. 常用资料以及官方网站 无人机飞控PX4用户使用手册&#xff08;无人机基本设置、地面站使用教程、软硬件搭建等&#xff09;&#xff1a;https://docs.px4.io/main/en/ PX4固件开源地址&#xff1a;https://github.com/PX4/PX4-Autopilot 飞控硬件、数传模块、GPS、分电板等…

详解MySQL在Windows上的安装

目录 查看电脑上是否安装了MySQL 下载安装MySQL 打开MySQL官网&#xff0c;找到DOWNLOADS 然后往下翻&#xff0c;找到MySQL Community(GPL) Downloads>> 然后找到MySQL Community Server 然后下载&#xff0c;选择No thanks,just start my download. 然后双击进行…

【git】(一)在vscode上使用git进行版本控制(结合指令、含示例)

vscode中的git插件将git操作从git指令简化到简单的图形界面操作&#xff0c;不用再去记忆git指令&#xff0c;操作简单直观了很多。第一次使用时&#xff0c;为了加深理解&#xff0c;我将一些基本操作和该操作底层使用的命令结合起来&#xff0c;并包含实例&#xff0c;方便学…

安卓入门二 Kotlin基础

Kotlin Kotlin的历史 Kotlin由Jet Brains公司开发设计&#xff0c;2011年公布第一版&#xff0c;2012年开源。 2016年发布1.0正式版&#xff0c;并且Jet Brains在IDEA加入对Kotlin的支持&#xff0c;安卓自此又有新的选择。 2019年谷歌宣布Kotlin成为安卓第一开发语言&#x…

【MATLAB第111期】基于MATLAB的sobol全局敏感性分析方法二阶指数计算

【MATLAB第111期】基于MATLAB的sobol全局敏感性分析方法二阶指数计算 一、简介 在MATLAB中计算Sobol二阶效应指数通常涉及到全局敏感性分析&#xff08;Global Sensitivity Analysis, GSA&#xff09;&#xff0c;其中Sobol方法是一种流行的技术&#xff0c;用于评估模型输入…

线段树例题题解

卫星覆盖&#xff08;NOI1997&#xff09; 题面&#xff1a; SERCOI&#xff08;Space-Earth Resource Cover-Observe lnstitute&#xff09; 是一个致力于利用卫星技术对空间和地球资源进行覆盖观测的组织。现在他们研制成功一种新型资源观测卫星 -SERCOI-308。这种卫星可以…

FFmpeg 编码和解码

文章目录 音频格式AACADIF音频数据交换格式ADTS音频数据传输流 音频解码音频编码 视频格式H264GOP图像组I帧&#xff0c;P帧&#xff0c;B帧H264压缩技术H264压缩级别H264视频级别H264码流结构SPSPPS 解码视频编码视频 音频格式 AAC AAC全称 Advanced Audio Coding&#xff0…

vue 组件库二次封装

vue 组件库二次封装 需求背景&#xff1a;项目使用arco-design组件库&#xff0c;ui 界面对于单选有统一的界面&#xff0c; 对于封装组件有一个大原则就是我们应该尽量保持原有组件的接口&#xff0c;除了我们需要封装的功能外&#xff0c;我们不应该改变原有组件的接口&#…

Kafka 幂等性与事务

文章目录 幂等性实现机制配置使用局限性 事务使用场景配置使用实现机制事务过程事务初始化事务开始事务提交事务取消事务消费 幂等性 Producer 无论向 Broker 发送多少次重复的数据&#xff0c;Broker 端只会持久化一条&#xff0c;保证数据不丢失且不重复。 实现机制 通过引…

LVS 负载均衡原理 | 配置示例

注&#xff1a;本文为 “ LVS 负载均衡原理 | 配置” 相关文章合辑。 部分内容已过时&#xff0c;可以看看原理实现。 未整理去重。 使用 LVS 实现负载均衡原理及安装配置详解 posted on 2017-02-12 14:35 肖邦 linux 负载均衡集群是 load balance 集群的简写&#xff0c;翻…

CannotRetrieveUpdates alert in disconnected OCP 4 cluster解决

环境&#xff1a; Red Hat OpenShift Container Platform (RHOCP) 4 问题&#xff1a; Cluster Version Operator 不断发送警报&#xff0c;表示在受限网络/断开连接的 OCP 4 集群中无法接收更新。 在隔离的 OpenShift 4 集群中看到 CannotRetrieveUpdates 警报&#xff1a; …

详解从输入url到页面渲染

当你在浏览器中输入一个 URL 并按下回车键&#xff0c;浏览器会经历一系列步骤来加载并渲染页面。这些步骤包括 DNS 解析、缓存处理、建立连接、发送请求、接收响应、解析 HTML、构建 DOM 树和 CSSOM 树、执行 JavaScript、布局和绘制等。以下是这些步骤的详细解释&#xff0c;…

Linux(Centos 7.6)目录结构详解

Linux(Centos 7.6)是一个操作系统&#xff0c;其核心设计理念是将一切资源抽象为文件&#xff0c;即一切皆文件。比如系统中的硬件设备硬盘、网络接口等都被视为文件。Windows系统一般是分为C、D、E盘。而Linux(Centos 7.6)是以斜线"/"作为文件系统的开始目录&#x…

【蓝桥杯选拔赛真题85】python摆放箱子 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析

目录 python摆放箱子 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python摆放箱子 第十五届蓝桥杯青少年组python比赛选拔赛真题详细解析 一…

数据分析思维(六):分析方法——相关分析方法

数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python&#xff0c;更重要的是数据分析思维。没有数据分析思维和业务知识&#xff0c;就算拿到一堆数据&#xff0c;也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》&#xff0c;本文内容就是提取…

小程序中引入echarts(保姆级教程)

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生…

【SQLi_Labs】Basic Challenges

什么是人生&#xff1f;人生就是永不休止的奋斗&#xff01; Less-1 尝试添加’注入&#xff0c;发现报错 这里我们就可以直接发现报错的地方&#xff0c;直接将后面注释&#xff0c;然后使用 1’ order by 3%23 //得到列数为3 //这里用-1是为了查询一个不存在的id,好让第一…

基于JAVA+SpringBoot+Vue的校园二手书交易平台

基于JAVASpringBootVue的校园二手书交易平台 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; …

快速掌握Elasticsearch检索之二:滚动查询(scrool)获取全量数据(golang)

Elasticsearch8.17.0在mac上的安装 Kibana8.17.0在mac上的安装 Elasticsearch检索方案之一&#xff1a;使用fromsize实现分页 1、滚动查询的使用场景 滚动查询区别于上一篇文章介绍的使用from、size分页检索&#xff0c;最大的特点是&#xff0c;它能够检索超过10000条外的…

【C++】深入理解 break 和 continue 语句

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;break 和 continue 介绍**break** 的作用**continue** 的作用注意事项 &#x1f4af;break 示例代码示例**执行结果****解析过程** &#x1f4af;continue 示例代码示例&am…