【数据结构】—— Java实现单链表

news2025/1/22 12:47:00

Java实现单链表

  • 一、一链表的概念及结构
  • 二、头节点与头指针的异同
  • 三、代码实现

一、一链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
在这里插入图片描述
注意:

  • 从上图可以看出,链式结构在逻辑上是连续的,但是在物理上不一定连续
  • 现实中结点一般是从堆上申请出来的。
  • 从堆上申请出来的空间,是按照一定策略来分配的,两次申请可能是连续,也可能是不连续的

二、头节点与头指针的异同

  • 头指针
    1.头指针是指链表指向第一个结点的指针,若链表有头节点,则是指向头节点的指针。
    2.头指针是具有标识作用,所以常用头指针冠以链表的命名
    3.无论链表是否为空,头指针均不为空。头指针是链表的必要元素
    若头指针为空,则链表不存在。
  • 头节点
    1.头结点是为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义(也可存放链表的长度)
    2.有了头结点,对在第一元素结点前插入结点和删除第一节点,其操作与其他结点的操作就统一了
    3.头节点不一定是链表的必须元素

三、代码实现

里面包含常用的一些操作:
1.头插法
2.尾插法
3.遍历
4.元素的删除

public class LinkedList {
    //创建结点类,结点脱离类一般无意义,所以设定为静态类
    static class Node {
        //数据域
        int val;
        //引用后继指针地址
        Node next;

        public Node(int val) {
            this.val = val;
        }
    }
    //定义头节点
    Node head;

    public void addFirst(int val) {
        Node node = new Node(val);
        if (head == null) {
            head = node;
            return ;
        }
        node.next = head;
        head = node;
    }
    //尾插法
    public void addLast(int val) {
        Node node = new Node(val);
        if (head == null) {
            head = node;
            return ;
        }
        //此时要定义一个临时头节点,以便我们找到链表的尾部
        //并且我们是不希望改动链表的头节点,所以临时结点很重要
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = node;
    }
    //任意位置插入,第一个数据节点为0号下标
    public boolean addIndex(int index,int val) {
        if (head == null) {
            return false;
        }
        //判断所给的索引合法性
        if (index < 0 || index > size()) {
            throw new RuntimeException("the index is not illegal!");
        }
        //第一个位置插入的时候,此时就是头插法
        if (index == 0) {
            addFirst(val);
            return true;
        }
        //最后一个位置插入则为尾插法
        if (index == size()) {
            addLast(val);
            return true;
        }
        //最后考虑中间位置的插入即可
        //1.定义临时头结点,先走到待插入位置的前一个位置
        Node temp = head;
        while (index > 1) {
            temp = temp.next;
            index--;
        }
        //2.对元素进行插入
        Node node = new Node(val);
        node.next = temp.next;
        temp.next = node;
        return true;
    }
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key) {
        if (head == null) {
            return false;
        }
        //只要在链表找到我们就返回false就行
        Node temp = head;
        while (temp != null) {
            if (temp.val == key) {
                return true;
            }
            temp = temp.next;
        }
        return false;
    }
    //删除第一次出现关键字为key的节点
    public void remove(int key) {
        if (head == null) {
            return ;
        }
        //只要存在我们才可以去删除
        if (!contains(key)) {
            throw new RuntimeException("the key is not exist !");
        }
        //如果是头节点的情况就直接删除
        if (head.val == key) {
            head  = head.next;
            return ;
        }
        //1.找到第一次出现的关键字key的前一个位置
        Node temp = head;
        while (temp != null && temp.next != null) {
            if (temp.next.val == key) {
                temp.next = temp.next.next;
                return;
            }
            temp = temp.next;
        }
    }
    //删除所有值为key的节点
    public void removeAllKey(int key) {
        if (head == null) {
            return ;
        }
        while (contains(key)) {
            remove(key);
        }
    }
    //得到单链表的长度
    public int size() {
        if (head == null) {
            return 0;
        }
        Node temp = head;
        int size = 0;
        while (temp != null) {
            size++;
            temp = temp.next;
        }
        return size;
    }
    public void display() {
        //遍历链表,这个是一定要掌握的,也不难
        if (head == null) {
            return ;
        }
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.val + " ");
            temp = temp.next;
        }
    }
    //清空链表
    public void clear() {
        //这个我们枪打出头鸟就行
        head =null;
    }

}

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

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

相关文章

MobPush for SDK API

推送监听接口 (addPushReceiver) 描述&#xff1a;添加推送监听&#xff0c;可监听接收到的自定义消息(透传消息)、通知消息、通知栏点击事件、别名和标签变更操作。 /*** com.mob.pushsdk.MobPush.class* MobPush推送监听接口* param receiver 监听*/ public static void ad…

Databend 开源周报 #74

Databend 是一款强大的云数仓。专为弹性和高效设计&#xff0c;自由且开源。 即刻体验云服务&#xff1a;https://app.databend.com。 What’s New 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 Features & Improvements Meta watch client …

【Word2021交叉引用参考文献格式】

Word2021交叉引用参考文献格式1 格式分类2 格式设置方法2.1 引用单个参考文献2.2 引用连续两个参考文献2.3 引用连续三个及三个以上的参考文献1 格式分类 按照引用参考文献的数量&#xff0c;格式一般分为三种&#xff1a; 1、引用单个参考文献&#xff0c;样例&#xff1a;我…

Leetcode回溯法题解

第一题 17. 电话号码的字母组合 题目描述&#xff1a;给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按任意顺序返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例1&#xff1a;…

Linux yum 使用手册,以及内网源搭建

Linux yum 内网源搭建 序 在 Linux 中&#xff0c;我们经常安装各个开源网站编写的代码、软件&#xff0c;在安装的时候各个软件之间有各种依赖关系&#xff0c;还可能出现版本问题&#xff0c;比如 Centos7 支持的软件&#xff0c; Centos6 就未必支持。如果是 Java 开发应该…

ArcGIS基础实验操作100例--实验73创建闭合线内部缓冲区

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验73 创建闭合线内部缓冲区 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff0…

K8S ReplicaSet 原理 示例 HPA扩容

K8S ReplicaSet 基本使用 K8S ReplicaSet 对象的作用是在任意时间点保持一组稳定的副本Pod运行&#xff0c;因此&#xff0c;它通常用于保证指定数量的相同Pod的可用性。乍一看&#xff0c; ReplicaSet 对象的定义跟 Replication Controller 并没有什么区别&#xff0c;都是维…

AI检测人员工衣工服着装不规范识别系统 yolo

AI检测人员工衣工服着装不规范识别系统基于opencvyolo网络深度学习模型对现场画面中人员着装穿戴实时监测分析。我们使用YOLO(你只看一次)算法进行对象检测。YOLO是一个聪明的卷积神经网络(CNN)&#xff0c;用于实时进行目标检测。该算法将单个神经网络应用于完整的图像&#x…

Vivado综合属性之SRL_STYLE

本文介绍综合属性SRL_STYLE取register、srl、srl_reg、reg_srl、reg_srl_reg和block中的值时&#xff0c;对Schematic的影响。 SRL_STYLE用于指导Vivado将SRL&#xff08;移位寄存器&#xff09;映射为何种形式。 目录 默认值 测试代码 原理图 SRL_STYLE配置为register …

【JavaSE】String类

目录 前言&#xff1a; 1.1、了解字符串构造方法 1.2、求字符串长度&#xff08;xxx.length()&#xff09; 1.3、isEmpty()方法 1.4、String对象的比较 1.4.1、通过&#xff08;str1 str2&#xff09;来比较&#xff0c;这样比较的是两个引用当中的地址 1.4.2、 boolea…

【ONE·C++ || vector (一)】

总言 学习笔记&#xff0c;慢慢补充。 文章目录总言1、整体介绍&#xff1a;2、常用各种接口介绍2.1、vector的基本结构&#xff1a;构造、析构、赋值2.1.1、总体情况预览2.1.2、各项函数使用演示2.2、vector增删查改相关2.2.1、增删查改总览2.2.2、如何在vector中插入、删除、…

Kotlin之使用协程编写高效的并发程序

文章目录1.协程的基本用法2.更多的作用域构建器3.使用协程简化回调的写法协程属于Kotlin中非常有特色的一项技术&#xff0c;因为大部分编程语言中是没有协程这个概念的。那么什么是协程呢&#xff1f;它其实和线程有点相似&#xff0c;可以简单地将它理解成一种轻量级的线程。…

Linux学习入门

1、Linux简介 操作系统分类&#xff1a;桌面操作系统、、服务器操作系统、移动端操作系统、嵌入式操作系统桌面操作系统主要针对个人电脑&#xff0c;Linux在桌面操作系统的应用主要有国产操作系统&#xff0c;Ubuntu。服务器操作系统有windows和linux以及苹果&#xff0c;主流…

微信小程序是如何实现快速编译的?

过往中小企业或技术团队开发一个 App 的时间成本和人力成本居高难下&#xff0c;但是随着微信上线小程序&#xff0c;更像是为这部分群体打开了一扇天窗&#xff0c;此后小程序呈现出井喷式发展的状态&#xff0c;不仅微信&#xff0c;支付宝、百度、抖音等超级 App 都跟上步伐…

线程进阶

常见的锁策略乐观锁 vs 悲观锁乐观锁&#xff1a;预测锁竞争不是很激烈悲观锁&#xff1a;预测锁竞争会很激烈轻量级锁 vs 重量级锁轻量级锁加锁解锁开销比较小&#xff0c;效率更高重量级锁加锁解锁开销比较大&#xff0c;效率更低多数情况下&#xff0c;乐观锁&#xff0c;也…

在CSDN年收入竟达五位数?----大学生技术自媒体成长之路

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 还有不到两周就要过年了&#xff0c;自己也马上迈入了21岁&#xff0c;感慨时间飞快&#xff0c;从19岁开始入驻C站&#xff0c;到现在也已经整整两年了&#xff0c;把自己最好的两年青春时光留在了CSDN&#xff0c;超百万…

定义输出格式的使用-printf()函数

目录&#x1f4d6;printf()函数简介格式化规定符格式控制特殊规定字符示例printf()函数简介 printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息。 printf()函数的调用格式为:printf("<格式化字符串>", <参量表>);这里看输出很简…

Lua入门学习

一、初识Lua脚本 Lua 是一种轻量小巧的脚本语言&#xff0c;用标准C语言编写并以源代码形式开放&#xff0c; 其设计目的是为了嵌入应用程序中&#xff0c;从而为应用程序提供灵活的扩展和定制功能。官网&#xff1a;https://www.lua.org/ 1、HelloWorld CentOS7默认已经安装…

什么是docker

文章目录简介Docker 架构特性局限Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c…

〖产品思维训练白宝书 - 产品思维认知篇⑨〗- 像 产品经理 一样去思考解决问题

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4e…