Java链表及源码解析

文章目录

  • 创建一个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());
    }
}


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

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

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

相关文章

潮玩宇宙方块兽系统开发:可定制UI与多种游戏内嵌助力个性化体验

潮玩宇宙方块兽系统开发正在推动潮玩与游戏的融合&#xff0c;通过个性化的UI设计和多游戏内嵌模式&#xff0c;为用户带来了独一无二的体验。本文将从可定制UI、多游戏内嵌功能以及系统实现等方面入手&#xff0c;探讨如何构建一个极具吸引力的潮玩宇宙方块兽系统。 一、可定制…

C#属性 Property

属性Property不是变量。 它们是由名为访问器方法来实现的一种方法。 实例属性表示的是实例的某个数据&#xff0c;通过这个数据反映实例当前的状态 静态属性表示的是类型的某个数据&#xff0c;通过这个数据反映类型当前的状态 意义&#xff1a; 防止恶意赋值(通过属性间接访问…

第八篇: 通过使用Google BigQuery进行数据批量和自动化处理

使用Python进行Google BigQuery数据批量和自动化处理 在大数据分析的日常工作中&#xff0c;定期更新、查询和处理数据是一项必不可少的任务。Google BigQuery结合Python脚本&#xff0c;可大幅简化这一过程。本文将介绍如何通过Python自动查询和更新BigQuery中的降水量数据&a…

AI - 人工智能;Ollama大模型工具;Java之SpringAI(三)

AI - 人工智能&#xff1b;Java之SpringAI&#xff08;一&#xff09; AI - 人工智能&#xff1b;Java之SpringAI&#xff08;二&#xff09; 一、Ollama 官网&#xff1a;https://ollama.com/ Ollama是一个大模型部署运行工具&#xff0c;在该工具里面可以部署运行各种大模型…

MySQL_数据类型建表

复习&#xff1a; 我们昨天学习的知识都忘了嘛&#xff1f;如果忘了也不要担心&#xff0c;我来带大家来复习一遍吧&#xff01;&#xff01;&#xff01; 1.查看所有数据库 show databases;2.创建属于自己的数据库 create database 数据库名; 检查自己创建的数据库是…

零基础入门进程间通信:task 1(匿名管道与vscode使用)

目录 引言 VSCODE使用 进程间通信正题 基础背景 进程间通信分类 匿名管道 理解匿名管道 代码实现 匿名管道的特性 管道的四种情况 应用场景 引言 在当今的计算机技术领域&#xff0c;操作系统作为计算机系统的核心组件&#xff0c;承担着资源管理、任务调度和进程管…

Vue 3 的 全局状态管理

1.思路梳理 工厂仓拣货信息&#xff1a;Factory Picking Info (FPI)工厂仓调度信息&#xff1a;Factory Scheduling Info (FSI)DC 收货信息&#xff1a;DC Receiving Info (DCRI)上架信息&#xff1a;Shelving Info (SI)盘点信息&#xff1a;Inventory Count Info (ICI)移位信…

Win系统通过命令行查看笔记本电池损耗/寿命/健康

在 Windows 10/11 系统中&#xff0c;可以通过指令查看笔记本电池的寿命情况&#xff0c;方法如下&#xff1a; 0&#xff0c;打开cmd/终端 键盘快捷键&#xff1a;Win R&#xff0c;然后输入cmd&#xff0c;点击【确定】 1&#xff0c;执行命令 在命令行中输入下面指令并按…

【DM系列】DM 集成 JDBC 开发指南

前言 数据库访问是数据库应用系统中非常重要的组成部分&#xff0c;DM 作为一个通用数据库管理系统&#xff0c;提供了多种数据库访问接口&#xff0c;包括 ODBC、JDBC、DPI 等方式。本开发指南详细介绍了 DM 的各种访问接口、相应开发环境的配置、以及一些开发用例。本指南的主…

【客观理性深入讨论国产中间件及数据库-科创基础软件】

随着国产化的进程&#xff0c;越来越多的国企央企开始要求软件产品匹配过程化的要求&#xff0c; 最近有一家银行保险的科技公司对行为验证码产品就要求匹配国产中间件&#xff0c; 于是开始了解国产中间件都有哪些厂家 一&#xff1a;国产中间件主要产品及厂商 1 东方通&…

python opencv3

三、图像预处理2 1、图像滤波 为图像滤波通过滤波器得到另一个图像。也就是加深图像之间的间隙&#xff0c;增强视觉效果&#xff1b;也可以模糊化间隙&#xff0c;造成图像的噪点被抹平。 2、卷积核 在深度学习中&#xff0c;卷积核越大&#xff0c;看到的信息越多&#xff0…

数据库管理-第258期 23ai:Oracle Data Redaction(20241104)

数据库管理258期 2024-11-04 数据库管理-第258期 23ai&#xff1a;Oracle Data Redaction&#xff08;20241104&#xff09;1 简介2 应用场景与有点3 多租户环境4 特性与能力4.1 全数据编校4.2 部分编校4.3 正则表达式编校4.4 随机编校4.5 空值编校4.6 无编校4.7 不同数据类型上…

Kettle——CSV文件转换成excel文件输出

1.点击—文件—新建—转换 拖入两个组件&#xff1a; 按shift&#xff0b;鼠标左击建立连接&#xff0c;并点击主输出步骤&#xff0c; 点击CSV文件输入&#xff0c;选择浏览的csv文件&#xff0c;然后点击确定 同样&#xff0c;Excel也同上&#xff0c;只是要删除这个xls 并…

【数据集】【YOLO】【目标检测】火情、烟雾、火灾检测数据集 9848 张,YOLO火灾检测算法实战训练教程!

数据集介绍 【数据集】火情、烟火、火灾检测数据集 9848 张&#xff0c;目标检测&#xff0c;包含YOLO/VOC格式标注。 数据集中包含2种分类&#xff1a;{0: Fire, 1: Smoke}&#xff0c;分别是‘火焰’和‘烟雾’。 数据集来自国内外图片网站和视频截图&#xff1b; 可用于…

Python酷库之旅-第三方库Pandas(202)

目录 一、用法精讲 941、pandas.CategoricalIndex.set_categories方法 941-1、语法 941-2、参数 941-3、功能 941-4、返回值 941-5、说明 941-6、用法 941-6-1、数据准备 941-6-2、代码示例 941-6-3、结果输出 942、pandas.CategoricalIndex.as_ordered方法 942-1…

docker 拉取MySQL8.0镜像以及安装

目录 一、docker安装MySQL镜像 搜索images 拉取MySQL镜像 二、数据挂载 在/root/mysql/conf中创建 *.cnf 文件 创建容器,将数据,日志,配置文件映射到本机 检查MySQL是否启动成功&#xff1a; 三、DBeaver数据库连接 问题一、Public Key Retrieval is not allowed 问题…

Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized

这里是Themberfue 在上一节的最后&#xff0c;我们讨论两个线程同时对一个变量累加所产生的现象 在这一节中&#xff0c;我们将更加详细地解释这个现象背后发生的原因以及该如何解决这样类似的现象 线程安全问题 public class Demo15 {private static int count 0;public …

如何使用RabbitMQ和Python实现广播消息

使用 RabbitMQ 和 Python 实现广播消息的过程涉及设置一个消息队列和多个消费者&#xff0c;以便接收相同的消息。RabbitMQ 的 “fanout” 交换机允许你将消息广播到所有绑定的队列。以下是如何实现这一过程的详细步骤。 1、问题背景 在将系统从Morbid迁移到RabbitMQ时&#x…

【RabbitMQ】04-发送者可靠性

1. 生产者重试机制 spring:rabbitmq:connection-timeout: 1s # 设置MQ的连接超时时间template:retry:enabled: true # 开启超时重试机制initial-interval: 1000ms # 失败后的初始等待时间multiplier: 1 # 失败后下次的等待时长倍数&#xff0c;下次等待时长 initial-interval…

java的类加载机制的学习

一、类加载的过程 一个类被加载到虚拟机内存中开始&#xff0c;到卸载出虚拟机内存为止&#xff0c;整个生命周期分为七个阶段&#xff0c;分别是加载、验证、准备、解析、初始化、使用和卸载。其中验证、准备和解析这三个阶段统称为连接。 除去使用和卸载&#xff0c;就是Ja…