Java链表及源码解析

news2024/11/27 8:22:42

文章目录

  • 创建一个ILindkedList接口创建方法(模拟实现链表方法)
  • 创建MyLinkedList来实现接口的方法
  • 创建链表节点
    • addFirst方法(新增头部属性)
    • addLast方法(新增到末尾一个属性)
    • remove方法(删除指定属性)
    • addIndex方法(任意位置添加一个元素属性)
    • removeAll(删除所有指定元素)
    • display打印
    • contains(链表中包含某个元素)
    • size(获取链表元素的数量)
  • clean(清空)
  • MyLinkedList代码如下:
  • Test代码:

  1. **链表是通过逻辑储存的方式通过节点的引用来获取元素值,每个节点包含两个部分 首先第一部分是value元素值。 第二部分是next来获取下个节点的地址,通过next来串联各个地址获取其中的value元素
    有序数组如果想要新增或者删减元素需要从头开始遍历逐个进行覆盖确保有序数组中的有序,时间复杂度为O(m*n)。
    链表的复杂度相对有序数组要方便他的时间复杂度分别是O(1)和O(N)。 **
    在这里插入图片描述

创建一个ILindkedList接口创建方法(模拟实现链表方法)

public interface ILinkedList {
    //首位置新增元素
    public void addFirst(int data);
    //最后位置新增元素
    public void addLast(int data);
    //在指定位置新增元素
    public void addIndex(int index,int data);
    //在链表中删除key元素
    public void remove(int key);
    //删除所有key的元素
    public void removeAll(int key);
    //打印链表元素
    public void display();
    //是否包含data
    public boolean contains(int data);
    //获取链表中元素的大小
    public  int size();
    void clean();
}

创建MyLinkedList来实现接口的方法

import javax.xml.soap.Node;

public class MyLinkedList implements ILinkedList{
    //创建一个static内部类来初始化节点属性
    static class NodeList{
        //元素值
        public int value;
        //节点指向的下一个地址
        public NodeList next;
        //构造方法只给value通过这个值来next下一个节点
        public NodeList(int value) {
            this.value = value;
        }
    }

创建链表节点

 //这里可以尝试创建一个链表
    public void createLinkedList(){
        NodeList node1=new NodeList(23);
        NodeList node2=new NodeList(25);
        NodeList node3=new NodeList(38);
        NodeList node4=new NodeList(55);
        //通过获取的对象来访问next链接下一个节点实现链接
        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        //这里node4的next节点为空值
        //head作为头部来访问各个节点
        this.head=node1;
    }

addFirst方法(新增头部属性)

在这里插入图片描述

 @Override
    public void addFirst(int data) {
    //增加一个元素到链表中,增加到头部
        //将data元素放入到类中
        NodeList node=new NodeList(data);
        NodeList cur=this.head;
        //这里node.next来获取头部地址
        node.next=head;
        //将node赋给head
        head=node;
    }

addLast方法(新增到末尾一个属性)

在这里插入图片描述

 @Override
    public void addLast(int data) {
        //增加一个元素到末尾
        NodeList node=new NodeList(data);
        NodeList cur=this.head;
        //这里我们查找最后一个位置的next节点是否为null,如果是null;
        while(cur.next!=null){
            cur = cur.next;
        }
        //循环出来cur.next的节点为null
        cur.next=node;
    }

remove方法(删除指定属性)

在这里插入图片描述

    @Override
    public void remove(int key) {
        //删除指定元素的next地址节点
        if(this.head==null){
            return;
        }
        //得到前缀
        NodeList cur = findRemoveKey(key);
        //判断返回值是否是空的
        if(cur==null){
            System.out.println("未找到该元素"+key);
            return;
        }
        //将cur.next给到dele得到节点
        NodeList dele=cur.next;
        //将后一个节点的next给到cur.next从而指向其他节点dele原有节点消失
        cur.next=dele.next;
    }
    private NodeList findRemoveKey(int key){
        NodeList cur=this.head;
        //cur.next不等于null数值
        while(cur.next!=null){
            if(cur.next.value==key){
                return cur;
            }
            //cur.next节点获取下一个cur
            cur = cur.next;
        }
        return null;
    }

addIndex方法(任意位置添加一个元素属性)

在这里插入图片描述

removeAll(删除所有指定元素)

在这里插入图片描述

   @Override
    public void removeAll(int key) {
        if(this.head==null){
            return;
        }
        NodeList pre=this.head;
        NodeList cur=pre.next;
        //cur!=null说明有数据
        while(cur!=null){
            //value值为key进入循环
            if(cur.value==key){
                //pre的下个节点为cur的下一个节点,取消掉cur=key这个节点的链接
                pre.next=cur.next;
                cur=cur.next;
            }else{
                //如果不等于pre要跳到cur的位置来继续作为前一项
                pre=cur;
                //cur获取下一项
                cur=cur.next;
            }
        }
        //不要忽略头部,如果是key要替换掉
        if(this.head.value==key){
            this.head=this.head.next;
        }
    }

    @Override
    public void addIndex(int index, int data)throws ErrorRuntimeExcepetion {
    //给一个位置,放入data元素
        //如果index的值小于0或者大于本身长度抛出异常显示下标
        try {
            if(index<0||index>size()){
                throw new ErrorRuntimeExcepetion("范围不准确"+index);
            }
        }catch (ErrorRuntimeExcepetion e){
            e.printStackTrace();
            return;
        }
        //如果index的位置是0或者index的位置是最后一个
        if(index==0){
            addFirst(data);
        }
        if(index==size()){
            addLast(data);
        }
        //走到这里index的值为其范围内容,首先获取index-1的位置
        NodeList cur = searchPre(index);
        //生成data元素链表
        NodeList node=new NodeList(data);
        if(cur==null){
            return;
        }
        //将原来cur.index的地址赋值给node.index来后移
        node.next=cur.next;
        //将现在的cur.index的地址指向node
        cur.next=node;
    }
    private NodeList searchPre(int index){
        NodeList cur=this.head;
        //求一个index-1的范围
        int count=0;
        while(count<index-1){
            cur=cur.next;
            count++;
        }
        //获取到index-1位置的cur
        return cur;
    }

display打印

 @Override
    public void display() {
        //创建一个对象接收head值,来进行打印
    NodeList cur=this.head;
    //cur不等于null
    while(cur!=null){
        //通过cur引用value来打印元素
        System.out.print(cur.value+" ");
        //通过next中下一个节点的地址来访问元素
        cur=cur.next;
    }
        System.out.println();
    }

contains(链表中包含某个元素)

   @Override
    public boolean contains(int data) {
        //链表中是否包含data
        NodeList cur=this.head;
        if(cur.value==data){
            //如果value是data返回true
            return true;
        }else{
            while(cur.next!=null){
                //循环每个节点判断是否为data
                if(cur.next.value==data){
                    return true;
                }
                cur=cur.next;
            }
        }
        return false;
    }

size(获取链表元素的数量)


    @Override
    public int size() {
        //获取链表的元素大小
        NodeList cur = this.head;
        //如果cur中为null没有任何元素大小是0
        if (cur == null) {
            return 0;
        }
        int count=0;//计数
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }

clean(清空)

在这里插入图片描述

   @Override
    public void clean() {
        if(this.head==null){
            return;
        }
        //将每个节点置为空属性并且回收
        NodeList cur=this.head;
        while(cur!=null){
            NodeList curNext=cur.next;
            cur.next=null;
            cur=curNext;
        }
        //置空null
        this.head=null;
    }

MyLinkedList代码如下:

import javax.xml.soap.Node;

public class MyLinkedList implements ILinkedList{
    //创建一个static内部类来初始化节点属性
    static class NodeList{
        //元素值
        public int value;
        //节点指向的下一个地址
        public NodeList next;
        //构造方法只给value通过这个值来next下一个节点
        public NodeList(int value) {
            this.value = value;
        }
    }
    //创建一个带头链表来获取当前的节点第一个元素
    public NodeList head;
    //这里可以尝试创建一个链表
    public void createLinkedList(){
        NodeList node1=new NodeList(23);
        NodeList node2=new NodeList(25);
        NodeList node3=new NodeList(38);
        NodeList node4=new NodeList(55);
        //通过获取的对象来访问next链接下一个节点实现链接
        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        //这里node4的next节点为空值
        //head作为头部来访问各个节点
        this.head=node1;
    }
    @Override
    public void addFirst(int data) {
    //增加一个元素到链表中,增加到头部
        //将data元素放入到类中
        NodeList node=new NodeList(data);
        NodeList cur=this.head;
        //这里node.next来获取头部地址
        node.next=head;
        //将node赋给head
        head=node;
    }

    @Override
    public void addLast(int data) {
        //增加一个元素到末尾
        NodeList node=new NodeList(data);
        NodeList cur=this.head;
        //这里我们查找最后一个位置的next节点是否为null,如果是null;
        while(cur.next!=null){
            cur = cur.next;
        }
        //循环出来cur.next的节点为null
        cur.next=node;
    }

    @Override
    public void remove(int key) {
        //删除指定元素的next地址节点
        if(this.head==null){
            return;
        }
        //得到前缀
        NodeList cur = findRemoveKey(key);
        //判断返回值是否是空的
        if(cur==null){
            System.out.println("未找到该元素"+key);
            return;
        }
        //将cur.next给到dele得到节点
        NodeList dele=cur.next;
        //将后一个节点的next给到cur.next从而指向其他节点dele原有节点消失
        cur.next=dele.next;
    }
    private NodeList findRemoveKey(int key){
        NodeList cur=this.head;
        //cur.next不等于null数值
        while(cur.next!=null){
            if(cur.next.value==key){
                return cur;
            }
            //cur.next节点获取下一个cur
            cur = cur.next;
        }
        return null;
    }

    @Override
    public void removeAll(int key) {
        if(this.head==null){
            return;
        }
        NodeList pre=this.head;
        NodeList cur=pre.next;
        //cur!=null说明有数据
        while(cur!=null){
            //value值为key进入循环
            if(cur.value==key){
                //pre的下个节点为cur的下一个节点,取消掉cur=key这个节点的链接
                pre.next=cur.next;
                cur=cur.next;
            }else{
                //如果不等于pre要跳到cur的位置来继续作为前一项
                pre=cur;
                //cur获取下一项
                cur=cur.next;
            }
        }
        //不要忽略头部,如果是key要替换掉
        if(this.head.value==key){
            this.head=this.head.next;
        }
    }

    @Override
    public void addIndex(int index, int data)throws ErrorRuntimeExcepetion {
    //给一个位置,放入data元素
        //如果index的值小于0或者大于本身长度抛出异常显示下标
        try {
            if(index<0||index>size()){
                throw new ErrorRuntimeExcepetion("范围不准确"+index);
            }
        }catch (ErrorRuntimeExcepetion e){
            e.printStackTrace();
            return;
        }
        //如果index的位置是0或者index的位置是最后一个
        if(index==0){
            addFirst(data);
        }
        if(index==size()){
            addLast(data);
        }
        //走到这里index的值为其范围内容,首先获取index-1的位置
        NodeList cur = searchPre(index);
        //生成data元素链表
        NodeList node=new NodeList(data);
        if(cur==null){
            return;
        }
        //将原来cur.index的地址赋值给node.index来后移
        node.next=cur.next;
        //将现在的cur.index的地址指向node
        cur.next=node;
    }
    private NodeList searchPre(int index){
        NodeList cur=this.head;
        //求一个index-1的范围
        int count=0;
        while(count<index-1){
            cur=cur.next;
            count++;
        }
        //获取到index-1位置的cur
        return cur;
    }

    @Override
    public void display() {
        //创建一个对象接收head值,来进行打印
    NodeList cur=this.head;
    //cur不等于null
    while(cur!=null){
        //通过cur引用value来打印元素
        System.out.print(cur.value+" ");
        //通过next中下一个节点的地址来访问元素
        cur=cur.next;
    }
        System.out.println();
    }

    @Override
    public boolean contains(int data) {
        //链表中是否包含data
        NodeList cur=this.head;
        if(cur.value==data){
            //如果value是data返回true
            return true;
        }else{
            while(cur.next!=null){
                //循环每个节点判断是否为data
                if(cur.next.value==data){
                    return true;
                }
                cur=cur.next;
            }
        }
        return false;
    }

    @Override
    public int size() {
        //获取链表的元素大小
        NodeList cur = this.head;
        //如果cur中为null没有任何元素大小是0
        if (cur == null) {
            return 0;
        }
        int count=0;//计数
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }

    @Override
    public void clean() {
        if(this.head==null){
            return;
        }
        //将每个节点置为空属性并且回收
        NodeList cur=this.head;
        while(cur!=null){
            NodeList curNext=cur.next;
            cur.next=null;
            cur=curNext;
        }
        //置空null
        this.head=null;
    }
}


Test代码:

public class Test {
    public static void main(String[] args) {
    MyLinkedList myLinkedList=new MyLinkedList();//这里创建链表对象
//    myLinkedList.createLinkedList();//访问创建的链表
        myLinkedList.addFirst(10);
        myLinkedList.addFirst(10);
        myLinkedList.addLast(10);
        myLinkedList.addLast(10);
        myLinkedList.addIndex(3,39);
       myLinkedList.addIndex(5,10);
        System.out.println(myLinkedList.contains(39));
        myLinkedList.display();
       myLinkedList.remove(39);
        myLinkedList.removeAll(10);
        myLinkedList.display();
        myLinkedList.clean();
        myLinkedList.addFirst(1);
        myLinkedList.display();
        System.out.println("链表中的元素大小为"+myLinkedList.size());
    }
}


#运行结果
在这里插入图片描述

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

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

相关文章

微服务系列四:热更新措施与配置共享

目录 前言 一、基于Nacos的管理中心整体方案 二、配置共享动态维护 2.1 分析哪些配置可拆&#xff0c;需要动态提供哪些参数 2.2 在nacos 分别创建共享配置 创建jdbc相关配置文件 创建日志相关配置文件 创建接口文档配置文件 2.3 拉取本地合并配置文件 2.3.1 拉取出现…

NoETL自动化指标平台为数据分析提质增效,驱动业务决策

直觉判断往往来源于多年的经验和专业知识&#xff0c;能够在复杂和不确定的环境中快速做出决策反应。但这种方式普遍存在主观偏见&#xff0c;缺乏合理的科学依据&#xff0c;无法全面、客观、精准地评估和识别市场趋势与用户需求&#xff0c;从而造成决策失误&#xff0c;给业…

使用亚马逊 S3 连接器为 PyTorch 和 MinIO 创建地图式数据集

在深入研究 Amazon 的 PyTorch S3 连接器之前&#xff0c;有必要介绍一下它要解决的问题。许多 AI 模型需要使用无法放入内存的数据进行训练。此外&#xff0c;许多为计算机视觉和生成式 AI 构建的真正有趣的模型使用的数据甚至无法容纳在单个服务器附带的磁盘驱动器上。解决存…

基于MATLAB的实现垃圾分类Matlab源码

⼀、垃圾分类 如何通过垃圾分类管理&#xff0c;最⼤限度地实现垃圾资源利⽤&#xff0c;减少垃圾处置量&#xff0c;改善⽣存环境质量&#xff0c;是当前世界各国共同关注的迫切问题之⼀。根据国家制定的统⼀标准&#xff0c;现在⽣活垃圾被⼴泛分为四类&#xff0c;分别是可…

硬件基础10 逻辑门电路——CMOS

目录 一、门电路类型 二、CMOS逻辑门 1、CMOS基础 2、MOS管开关电路 &#xff08;1&#xff09;、基础理论分析 &#xff08;2&#xff09;、开关动态特性 3、CMOS反相器 4、与非、或非门 三、逻辑门的不同输出结构与参数 1、CMOS的保护和缓冲 2、漏极开路与三态输出…

新手散户如何避免被割?有量化策略适应暴涨暴跌行情吗?|附代码

这是邢不行第 124 期量化小讲堂的分享 作者 | 邢不行 大A今年上半年的行情较为坎坷&#xff0c;市场持续下跌&#xff0c;导致诸多投资者风格大变&#xff0c;从倾向于高风险的进攻策略转为低风险的防御策略&#xff0c;尤以高股息策略和杠铃策略最为火爆。 本文给大家介绍一…

数据链路层Mac协议与ARP协议

Mac帧 ​ ​ 如何将有效载荷和报头分离&#xff1f; 根据固定大小 ​​ 报头固定大小&#xff0c;按报头大小分离 如何分用&#xff1f; ​​​​ 类型为0800&#xff0c;代表为IP报文&#xff0c;应该交给网络层IP协议 目的地址 原地址为Mac地址 局域网通信 ​ 局…

轮椅车、医用病床等康复类器具检测设备的介绍

康复类器具检测设备是指用于检测、评估和测试康复类器具的设备。康复类器具包括轮椅、助行器、假肢、矫形器等。这些器具在使用前需要经过检测和评估以确保其满足质量、性能、安全和有效性的要求。 康复类器具的测试项目及其设备主要包括以下几种&#xff1a; 1、力学测试设…

WiFi一直获取不到IP地址是怎么回事?

在当今这个信息化时代&#xff0c;WiFi已成为我们日常生活中不可或缺的一部分。无论是家庭、办公室还是公共场所&#xff0c;WiFi都为我们提供了便捷的无线互联网接入。然而&#xff0c;有时我们可能会遇到WiFi连接后无法获取IP地址的问题&#xff0c;这不仅影响了我们的网络使…

基于SSM+VUE儿童接种疫苗预约管理系统JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

城镇住房保障:SpringBoot系统架构解析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

软件测试—功能测试详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、测试项目启动与研读需求文档 &#xff08;一&#xff09; 组建测试团队 1、测试团队中的角色 2、测试团队的基本责任 尽早地发现软件程序、系统或产…

第十五届蓝桥杯C/C++B组题解——数字接龙

题目描述 小蓝最近迷上了一款名为《数字接龙》的迷宫游戏&#xff0c;游戏在一个大小为N N 的格子棋盘上展开&#xff0c;其中每一个格子处都有着一个 0 . . . K − 1 之间的整数。游戏规则如下&#xff1a; 从左上角 (0, 0) 处出发&#xff0c;目标是到达右下角 (N − 1, N …

【9695】基于springboot+vue的学生就业管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取免费源码 项目描述 本学生就业管理系统以springboot作为框架&#xff…

Android使用scheme方式唤醒处于后台时的App场景

场景&#xff1a;甲App唤醒处于后台时的乙App的目标界面Activity&#xff0c;且乙App的目标界面Activity处于最上层&#xff0c;即已经打开状态&#xff0c;要求甲App使用scheme唤醒乙App时&#xff0c;达到跟从桌面icon拉起App效果一致&#xff0c;不能出现只拉起了乙App的目标…

centos7,yum安装mongodb

yum安装mongodb 1.配置MongoDB的yum源2.安装Mongodb3.启动Mongodb4.配置远程访问5.设置mongo密码 1.配置MongoDB的yum源 1.创建yum源文件&#xff0c;输入命令&#xff1a; vim /etc/yum.repos.d/mongodb-org-5.0.repo然后在文件中输入以下内容并保存&#xff1a; [mongodb-…

SpringBoot项目集成ONLYOFFICE

ONLYOFFICE 文档8.2版本已发布&#xff1a;PDF 协作编辑、改进界面、性能优化、表格中的 RTL 支持等更新 文章目录 前言ONLYOFFICE 产品简介功能与特点Spring Boot 项目中集成 OnlyOffice1. 环境准备2. 部署OnlyOffice Document Server3. 配置Spring Boot项目4. 实现文档编辑功…

【华为HCIP实战课程31(完整版)】中间到中间系统协议IS-IS路由汇总详解,网络工程师

一、IS-IS的汇总 1、可以有效减少在LSP中发布的路由条目,减小对系统资源的占用。 2、会减少LSP报文的扩散,接收到该LSP报文的其他设备路由表中只会出现一条聚合路由。 3、可以避免网络中的路由震荡,提高了网络的稳定性。 4、被聚合的路由可以是IS-IS路由,也可以是被引入…

LabVIEW编程过程中为什么会出现bug?

在LabVIEW编程过程中&#xff0c;Bug的产生往往源自多方面原因。以下从具体的案例角度分析一些常见的Bug成因和调试方法&#xff0c;以便更好地理解和预防这些问题。 ​ 1. 数据流错误 案例&#xff1a;在一个LabVIEW程序中&#xff0c;多个计算节点依赖相同的输入数据&#…

Vatee万腾平台:让企业数字化转型更轻松、更高效

在数字化浪潮席卷全球的今天&#xff0c;企业数字化转型已成为不可逆转的趋势。然而&#xff0c;对于许多企业来说&#xff0c;数字化转型并非易事&#xff0c;它涉及到技术、人才、流程等多个方面的变革。为了帮助企业顺利实现数字化转型&#xff0c;Vatee万腾平台应运而生&am…