单向链表理解——java

news2024/11/13 16:04:14

概述

单线链表:单向链表又叫单链表,是链表的一种。由节点构成,head指针指向第一个称为表头节点,而终止指向最后一个null指针

特点

  • 链表连接的方向都是单向的
  • 链表的访问要通过顺序从头部开始
  • 链表是使用指针进行构造的列表
  • 是由一个一个节点组成的链表,又称为节点链表
  • 每个节点都有指针成员变量指向链表中的下个节点

结构 

 说明:可以比喻成火车,head是火车头data是火车厢,每一个火车厢的车厢next都拉着一个下一个车厢

优点

  1. 单个节点的创建非常方便(增)
  2. 节点的删除非常方便,不需要线性结构那样移动数据(删)

缺点

  1. 只能冲头到位遍历,只能后续,无法找到前驱,也就是只能前进
  2. 查询时搜索遍历需要遍历整个链表,在不好的情况下,可能需要道链尾才能找到
  3. 链表需要维护next域,暂用内存

案例

创建一个单向列表

public class Node {
    //存储节点的值
    int val;
    //下一个节点地址
    Node next;

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

    public Node(int val, com.study.data.linked.Node next) {
        this.val = val;
        this.next = next;
    }

}

 测试        

1、插头法,从头部上添加数据

输出结果:5->4->3->3->2->NULL

 //实际存储的个数,相当于火车车厢的个数
    private int size;
    //第一个节点,相当于火车头
    private Node head;

    //在头部上增加链数据(插头罚),如果链表为空,那么就是增加火车头
     public void addFirst(int data) {
        //要向链表中添加节点,要判断当前的链表是否为空,如果一个都没有,那么就要插入第一个节点
        Node node = new Node(data);
        if (size == 0) {
            head = node;
            size++;
        } else {
            //当前的火车已经存在节点了
            // 头部为上一个节点
            node.next = head;
            head = node;
            size++;
        }
    }

    /**
     * 用来展示链表
     * @return
     */
    public String showNode() {
        StringBuilder ret = new StringBuilder();
        Node node = head;
        while (node != null) {
            ret.append(node.val).append("->");
            // 继续访问下一节车厢
            node = node.next;
        }
        ret.append("NULL");
        return ret.toString();
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        System.out.println(test.showNode());
    }

2、插尾法(从尾部开始插入数据)

输出结果:2->3->3->4->5->NULL

//插尾法,从尾部开始添加数据
    public void addLast(int data) {
        //要向链表中添加节点,要判断当前的链表是否为空,如果一个都没有,那么就要插入第一个节点
        Node node = new Node(data);
        if (size == 0) {
            head = node;
            size++;
        } else {
            //当前的火车已经存在节点了
            Node last = head;
            while (last.next != null) {
                last = last.next;
            }
            // 头部为上一个节点
            last.next = node;
            size++;
        }
    }
    
    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addLast(2);
        test.addLast(3);
        test.addLast(3);
        test.addLast(4);
        test.addLast(5);
        System.out.println(test.showNode());
    }

 3、在链表的中间插入位置

输出结果:5->4->4->3->3->2->NULL

图片详解

代码实现

 //在链表的中间插入位置
    public void addIndex(int index, int data) {
        //判断边界条件,判断index的合法性
        if (index < 0 || index > size) {
            System.out.println("插入链表位置失败....");
            return;
        }
        if (index == 0) {
            // 从链表的头部开始插入
            addFirst(data);
            return;
        }
        //说明此时index合法,并且时在中间这个位置,此时需要知道index的前驱节点,单链表只能从前往后遍历
        //将要插入的链表值添加进去
        Node node = new Node(data);
        //获取到整个链表值
        Node result = head;
        for (int i = 0; i < index - 1; i++) {
            //移除大于index-1的头部数据
            result = result.next;
        }
        //将上面尾巴数据赋值过去,要注意这里时next,所以实际上是head的next,比如4 0 1 ,next的话是0 1
        //node的数据还是刚刚添加的数据,这个时候就会变成了data+result.next的数据
        node.next = result.next;
        //将result中的next对node进行替换,上面的node已经完成了拼接
        result.next = node;
        size++;
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        test.addIndex(2,4);
        System.out.println(test.showNode());
    }

4、获取下标中的数据

输出结果:4

 // 查询index节点上的数据
    public int get(int index) {
        if (index < 0 || index >= size) {
            System.out.println("获取链表位置index值失败...");
            return -1;
        }
        //获取到前一个节点
        Node node = head;
        for (int i = 0; i < index; i++) {
            node = node.next;
        }
        return node.val;
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        System.out.println(test.showNode());
        System.out.println("获取节点1的数据" + test.get(1));
    }

5、对链表中某个值进行替换

输出结果:5->4->0->3->2->NULL

//对下标的某个值进行替换
    public int set(int index, int data) {
        if (index < 0 || index >= size) {
            System.out.println("修改单链表中的数据失败");
            return -1;
        }
        Node node = head;
        for (int i = 0; i < index; i++) {
            node = node.next;
        }
        //需要替换位置的值
        int oldData = node.val;
        // 进行值替换
        node.val = data;
        return oldData;
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        test.set(2,0);
        System.out.println(test.showNode());
    }

6、判断链表是否包含某个值

输出:true

// 判断链表中是否包含元素data
    public boolean contains(int data) {
        Node node = head;
        while (node != null) {
            if (node.val == data) {
                System.out.println("找到了元素" + data);
                return true;
            }
            node = node.next;
        }
        System.out.println("没有找到元素" + data);
        return false;
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        System.out.println(test.contains(5));
        System.out.println(test.showNode());
    }

7、移除链表中第一个值

输出结果:4->3->3->2->NULL

//移除第一个值
    public void removeFirst() {
        if (size == 0) {
            return;
        }
        Node node = head;
        head = node.next;
        node.next = null;
        size--;
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        test.removeFirst();
        System.out.println(test.showNode());
    }

8、通过下标移除对应的值

输出结果:5->4->3->2->NULL

//通过下标移除值
    public void removeIndex(int index) {
        if (index < 0 || index > size) {
            System.out.println("通过下标移除失败,下标异常");
        }
        if (index == 0) {
            removeFirst();
        } else {
            Node node = head;
            for (int i = 0; i < index - 1; i++) {
                node = head.next;
            }
            // node是待删除的头部节点,del就是你要删除的节点
            Node del = node.next;
            //将两个节点给连接起来
            node.next = del.next;
            del.next = null;
            size--;
        }
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        test.removeIndex(2);
        System.out.println(test.showNode());
    }

9、删除指定元素的第一个节点

输出:5->4->3->2->NULL

//删除指定元素的第一个节点
    public void removeValueFirst(int data) {
        //先判断头节点情况,看看头节点是不是正好等于待删除节点
        if (head.val == data) {
            removeFirst();
        } else {
            //先找到待删除的节点
            Node node = head;
            while (node.next != null) {
                //找到待删除节点,找到了以后可以直接删除
                if (node.next.val == data) {
                    Node del = node.next;
                    node.next = del.next;
                    del.next = null;
                    size--;
                    break;
                } else {
                    node = node.next;
                }
            }
        }
    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        test.removeValueFirst(3);
        System.out.println(test.showNode());
    }

10、删除链表中的所有节点

输出结果:5->4->2->NULL

//删除链表中包含值的所有节点
    public void removeValueAll(int data) {
        //判断头节点
        while (head != null && head.val == data) {
            removeFirst();
        }
        if (head == null) {
            System.out.println("当前节点已经为空了!");
            return;
        }
        //头节点处理完毕,并且链表不等于空
        Node node = head;
        while (node.next != null) {
            //12345
            if (node.next.val == data) {
                Node del = node.next;
                node.next = del.next;
                del.next = null;
                size--;

            } else {
                node = node.next;
            }
        }

    }

    public static void main(String[] args) {
        NodeTest test = new NodeTest();
        test.addFirst(2);
        test.addFirst(3);
        test.addFirst(3);
        test.addFirst(4);
        test.addFirst(5);
        test.removeValueAll(3);
        System.out.println(test.showNode());
    }

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

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

相关文章

Python读取Excel文件

最近需要用到Python来操作excel表&#xff0c;读取表格内容到数据库。所以就搜索了相关资料。 查找了一下&#xff0c;可以操作excel表的几个库有以下几个&#xff1a; openpyxl 这个是推荐使用的库&#xff0c;可以读写Excel 2010以上格式&#xff0c;以.xlsx结尾的文件。 x…

SpringBoot+Vue项目校园二手交易平台

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

HCI opcode

HCI控制命令由两个字节的OpCode定义&#xff0c;每个OpCode由一个字节的OGF&#xff08;OpCode Group Field&#xff09;和一个字节的OCF&#xff08;OpCode Command Field&#xff09;组成。参考&#xff1a; HCI Command Packet Command的数据包格式如下图&#xff1a; 其中…

海量数据下查询慢、数据不一致难题如何解?看某游戏公司的技术实践

导语&#xff1a; 复杂架构的危害是隐性且持续增长的&#xff0c;尤其在海量数据处理的业务场景下&#xff0c;导致系统吞吐量增长、各功能模块相互影响&#xff0c;且数据重复、维护困难。某游戏公司就面临这样的困境&#xff0c;在寻求解决方案的过程中&#xff0c;携手Ocean…

通用的异常处理程序机制与处理返回值方案

通用的异常处理程序机制与返回值方案文章目录通用的异常处理程序机制与返回值方案现状示例方案原理步骤总结附完整代码现状相信很多人都为处理错误返回值代码都烦恼过。例如&#xff1a;一个程序嵌套了10个方法&#xff0c;嵌套最深的方法一旦有个业务错误代码&#xff0c;那么…

如何通过文档改善用户体验和客户关系

文档对你的员工和客户来说都是一个宝贵的信息来源。你策划和分享的每一个教程、"如何做 "的文章和指南都可以改善用户体验和客户关系。 在这个数字时代&#xff0c;每个人都希望立即得到答案&#xff0c;很少或没有人际互动&#xff0c;一个坚实的知识库软件使你领先…

TIOBE12月编程语言榜发布:C++首超Java!

本月TIOBE更新了榜单&#xff0c;其中变化最大的莫过于C以0.12%微弱优势&#xff0c;总市场份额首次超过了Java。 在今年6月份的时候&#xff0c;TIOBE的CEOPaul Jansen曾做出过预测&#xff0c;C将会是下一个超越Java的语言。果然在最新版本的C 20的推动下&#xff0c;超越了…

模板方法模式(python)

一、模式定义 1.模板方法模式(Template Method Pattern)&#xff1a;定义一个操作中算法的框架&#xff0c;而将一些步骤延迟到子类中&#xff0c;模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 2.模板方法是一种类行为型模式。 二、模式结构 …

斩获三奖 | 国产BI行业唯一获奖,Smartbi荣获36氪、数据猿等多项荣誉

入选36氪新经济之王年度企业近日&#xff0c;36氪WISE2022 新经济之王盛会隆重举行&#xff0c;会上正式发布了“WISE2022 新经济之王年度企业”名册&#xff0c;思迈特软件成功斩获“WISE2022 新经济之王年度企业”荣誉&#xff0c;成为国产BI行业唯一获奖品牌。据了解&#x…

scrapy爬虫框架

scrapy爬虫框架一 scrapy架构介绍二 安装指南三 创建项目3.1 创建爬虫项目3.2 创建爬虫3.3 启动爬虫3.4 pycharm中运行四 scrapy解析数据五 settings相关配置六 持久化方案七 全站爬取cnblogs文章八 中间件一 scrapy架构介绍 Scrapy一个开源和协作的框架&#xff0c;其最初是为…

在线购物电商网站毕业设计,网上购物商城系统设计与实现,毕业设计怎么写论文毕设源码开题报告需求分析怎么做

项目背景和意义 目的&#xff1a;伴随着互联网技术的不断发展和完善&#xff0c;在人们的生活和工作的各个方面&#xff0c;互联网都有着非常重大的影响。伴随着国内电子商务行业的迅猛发展&#xff0c;消费者现在能够轻松的实现足不出户的&#xff0c;仅仅通过网络购物平台就可…

【工作经历分享】软件测试求职真的难,但是我还是从7K涨到了14K

上个礼拜刚好转正了&#xff0c;三个月试用期&#xff0c;五月份换的工作。 现在这份工作&#xff0c;相比上一份确实好很多&#xff0c;比如工资直接涨了一倍&#xff0c;7到14&#xff0c;13薪&#xff0c;朝九晚六&#xff0c;从不加班&#xff0c;项目也简单&#xff0c;包…

Kubernetes基础概念

什么是Kubernetes 1.用于自动部署、扩展和管理“容器化( containerized) 应用程序”的开源系统 2.可以理解成K8S是负责自动化运维管理多个容器化程序(比如Docker)的集群&#xff0c;是–个生态极其丰富的容器编排框架工具 Kubernetes作用 1.用于自动部署、扩展和管理“容器化…

2022下半年的软考成绩公布时间?

今年软考下半年成绩公布时间预估在12月15-20日左右。 软考成绩一般并没有一个固定的时间点公布&#xff0c;不过从近几年软考办成绩查询通知公布时间来看&#xff0c;大多是下午出的成绩。一般来说&#xff0c;成绩查询通知公布之前的几分钟&#xff0c;考生已经可以查成绩了。…

使用Golang语言walk框架开发一个简单的windowsGUI

1、前言 最近使用golang语言开发了一个windowsGUI的Demo&#xff0c;由于golang语言属于比较新的语言&#xff0c;对GUI开发这一块并没有原生库也没有推荐库&#xff0c;因此我在github上找到了一个叫做walk的GUI开发框架。 github原址为&#xff1a;http://github.com/lxn/w…

定时执行专家 —— 定时循环发送TCP消息(例如:控制设备的开关机等场景)

《定时执行专家》是一款制作精良、功能强大、简单易用、毫秒级精度、专业级的定时任务执行软件。软件具有 21 种【任务类型】、12 种【触发器】触发方式&#xff0c;并且全面支持界面化Cron表达式设置。软件采用多线程并发方式检测任务触发和任务执行&#xff0c;能够达到毫秒级…

带你快速入门JDBC

1&#xff0c;JDBC概述 在开发中我们使用的是java语言&#xff0c;那么势必要通过java语言操作数据库中的数据。这就是接下来要学习的JDBC。 1.1 JDBC概念 JDBC 就是使用Java语言操作关系型数据库的一套API 全称&#xff1a;( Java DataBase Connectivity ) Java 数据库连接 …

Win11的两个实用技巧系列之开机后桌面无响应怎么办?

目录 win10开机后桌面无响应怎么办?win10开机后桌面无响应点什么都不行 win10开机后桌面无响应点什么都不行怎么办&#xff1f; Win10和Win11 22H2如何关闭文字热门搜索? Win11 22H2关闭文字热门搜索 Win10 22H2关闭文字热门搜索 点击拿去 win10开机后桌面无响应怎么办…

NR PUSCH power control

这篇看下NR PUSCH power control的相关内容&#xff0c;主要内容集中在38.213 7.1章节&#xff0c;功率计算无非就是一个长公式&#xff0c;根据RRC配置的参数及后续DCI field 的内容作出功率的调整&#xff1b;最初这部分看的就云里雾里的&#xff0c;最近再看&#xff0c;相比…

环境土壤物理模型HYDRUS

HYDRUS是由著名土壤学家Rien van Genuchten和Jirka Simunek等人基于Windows系统界面开发的环境土壤物理模拟软件&#xff0c;是模拟一维和多维变饱和多孔介质的水流、溶质运移、根系吸水和溶质吸收、热量传输等的强有力工具。除基础功能以外&#xff0c;该模型还附有一系列扩展…