数据结构之单链表基本操作

🤷‍♀️🤷‍♀️🤷‍♀️ 今天给大家分享的是单链表的基本操作。

清风的个人主页 

🎉欢迎👍点赞✍评论❤️收藏

😛😛😛希望我的文章能对你有所帮助,有不足的地方还请各位看官多多指教,大家一起学习交流!

动动你们发财的小手,点点关注点点赞!在此谢过啦!哈哈哈!😛😛😛

 

目录

 一、接口定义

二、类定义

三、方法实现

3.1创建单链表(初始化创建)

3.2头插法插入节点

3.3尾插法插入节点

3.4指定位置插入节点

3.5判断节点是否包含在链表中

3.6删除值为key的节点

 3.7删除所有值为key的节点

3.8得到链表长度

3.9清空链表

3.10显示链表(打印)


源码链接:>清风的Gitee主页 

 一、接口定义

还是和之前的顺序表一样,定义一个接口。后续通过链表类去实现这个定义的接口。

interface SingleLinkedList {
    //头插法
    void addFirst(int data);
    //尾插法
    void addLast(int data);
    //任意位置插入,第一个数据节点为0号下标
    void addIndex(int index,int data);
    //查找是否包含关键字key是否在单链表当中
    boolean contains(int key);
    //删除第一次出现关键字为key的节点
    void remove(int key);
    //删除所有值为key的节点
     void removeAllKey(int key);
    //得到单链表的长度
     int size();
     void clear();
     void display();
}

二、类定义

定义一个链表类,它是由各个节点构成的,因此还需要在链表类内定义一个关于节点的内部类。代码如下:
 

public class MyLinkedList implements SingleLinkedList {

    class LinkNode {
        public int val;
        public LinkNode next;

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

    public LinkNode head;
}

三、方法实现

3.1创建单链表(初始化创建)

每次通过LinkNode类定义的节点去new一个新的节点并通过构造函数设置初始值,节点定义完成后,通过各个节点的next域把各个节点之间联系起来,便成功创建了一个单链表。

    public void creatLinkedList() {
        LinkNode node1 = new LinkNode(12);
        LinkNode node2 = new LinkNode(23);
        LinkNode node3 = new LinkNode(34);
        LinkNode node4 = new LinkNode(45);
        LinkNode node5 = new LinkNode(56);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;

        this.head = node1;

    }

3.2头插法插入节点

    //头插法
    public void addFirst(int data) {
        LinkNode newnode = new LinkNode(data);
        if (this.head == null) {
            this.head = newnode;
        } else {
            newnode.next = this.head;
            this.head = newnode;
        }
    }

3.3尾插法插入节点

尾插法插入节点时,首先要找到单链表的最后一个节点,再去插入。 

  • 注意,找到单链表的最后一个节点,在while循环里面的控制条件是:cur.next!=null,而不是cur!=null,这一点要切记!!!在我们刷题的时候,很多情况下都要去遍历找节点,因此一定要注意。(cur是一个引用,从head开始遍历)
  • 下图是while(cur.next!=null),循环条件结束的时候,cur所指向的位置:>

 

  • 下图是while(cur!=null),循环条件结束的时候,cur所指向的位置:> 

 

    public void addLast(int data) {
        LinkNode newnode = new LinkNode(data);
        if (this.head == null) {
            this.head = newnode;
            return;
        }
        LinkNode cur = this.head;
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = newnode;

    }

3.4指定位置插入节点

在指定位置插入,首先要判断插入位置是否合法。其次,若是在头节点插入,调用头插法即可,若是在尾节点插入,调用尾插法即可。然后,就需要找到指定的位置,此时应该找的是指定位置的前驱节点,通过指定位置的前驱节点的next域指向要插入的节点即可。当然在执行这一步骤之前,我们还需要先把前驱节点的next域所指向的节点交给要插入的节点的next域。

    public void addIndex(int index, int data) {
        if (index < 0 || index > size()) {
            System.out.println("插入位置不合法:>" + index);
            return;
        }
        if (index == 0) {
            addFirst(data);
            return;
        }
        if (index == size()) {
            addLast(data);
            return;
        }
        LinkNode cur = this.head;
        LinkNode newnode = new LinkNode(data);
        for (int i = 0; i < index - 1; i++) {
            cur = cur.next;
        }
        newnode.next = cur.next;
        cur.next = newnode;
    }

3.5判断节点是否包含在链表中

只需遍历链表,比较节点的值是否和要判断节点的值相等即可。

    public boolean contains(int key) {
        LinkNode cur = this.head;
        while (cur != null) {
            if (cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

3.6删除值为key的节点

要先找到值为key的节点的前驱节点:

    private LinkNode findPrev(int key) {
        LinkNode cur = this.head;
        while ((cur.next != null)) {
            if (cur.next.val == key) {
                return cur;
            }
            cur = cur.next;
        }
        return cur;
    }

以下图为例,假设删除34:>

    public void remove(int key) {
        if (this.head == null) {
            System.out.println("链表为空,无法删除!!!");
            return;
        }
        if (this.head.val == key) {
            this.head = this.head.next;
            return;
        }
/*        while(cur.next!=null){
            //找到要删除节点的前驱
            if(cur.next.val==key){
                LinkNode del=cur.next;
                cur.next=del.next;
                return;

            }else {
                cur=cur.next;
            }
        }*/
        LinkNode prev = findPrev(key);
        if (prev == null) {
            System.out.println("无要删除的数字:>" + key);
            return;
        }
        LinkNode del = prev.next;
        prev.next=del.next;
    }

 3.7删除所有值为key的节点

方法是通过双指针来解决:>

假设删除值为23的所有节点。

cur往前走,发现值为23的节点,进行删除操作:>

删除之后,prev指向了23的下一个节点。

 

删除完成后,prev不动,cur继续往后遍历:>

 

当cur这个引用所指向的节点的值不是23是,prev也要继续往前挪:>

 

如此进行下去,即可删除所有值为23的节点。

下面是实现代码:> 

    public void removeAllKey(int key) {
        if (this.head == null) {
            System.out.println("链表为空!");
            return;
        }
        LinkNode prev = head;
        LinkNode cur = head.next;
        while (cur != null) {
            if (cur.val == key) {
                prev.next = cur.next;
                cur = cur.next;
            } else {
                prev = cur;
                cur = cur.next;
            }
        }
        if (head.val == key) {
            head = head.next;
        }
    }

3.8得到链表长度

很简单,只需通过一个引用遍历即可。如果引用所指的对象不是空,那么计数器+1。

    public int size() {
        LinkNode cur = this.head;
        int count = 0;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

3.9清空链表

    public void clear() {
        LinkNode cur = this.head;
        while (cur != null) {
            LinkNode curNext = cur.next;
            cur.next = null;
            cur = curNext;
        }
        head.next = null;
    }

3.10显示链表(打印)

    public void display(LinkNode newhead) {
        LinkNode cur = newhead;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

🎉好啦,今天的分享就到这里!!

✨创作不易,还希望各位大佬支持一下!

👍点赞,你的认可是我创作的动力!

⭐收藏,你的青睐是我努力的方向!

✏️评论:你的意见是我进步的财富!

 

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

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

相关文章

大数据毕业设计选题推荐-农作物观测站综合监控平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

计算当月工作日时间进度

目录 1.按一个月平均算 2.除去星期六星期天算 3.自定义节假日算 1.按一个月平均算 // 获取当前时间 const now new Date(); // 获取当前年份和月份 const currentYear now.getFullYear(); const currentMonth now.getMonth() 1; // 计算当月天数 const daysInMonth ne…

【Docker】iptables基本原理

在当今数字化时代&#xff0c;网络安全问题变得越来越重要。为了保护我们的网络免受恶意攻击和未经授权的访问&#xff0c;我们需要使用一些工具来加强网络的安全性。其中&#xff0c;iptables是一个强大而受欢迎的防火墙工具&#xff0c;它可以帮助我们控制网络流量并保护网络…

【剑指offer|图解|双指针】训练计划 I + 删除有序数组中的重复项

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、算法模板 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️训练计划 I二. ⛳️查找总价格为目标值的两个商品三. ⛳️删除有序数组中的…

【JAVA学习笔记】67 - 坦克大战1.5 - 1.6,防止重叠,记录成绩,选择是否开新游戏或上局游戏,播放游戏音乐

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter20/src 增加功能 1.防止敌人坦克重叠运动 2.记录玩家的成绩&#xff0c;存盘退出 3.记录当时的敌人坦克坐标&#xff0c;存盘退出 4.玩游戏时&#xff0c;可以选择是开新游戏还是继续上局…

尚硅谷大数据项目《在线教育之实时数仓》笔记007

视频地址&#xff1a;尚硅谷大数据项目《在线教育之实时数仓》_哔哩哔哩_bilibili 目录 第9章 数仓开发之DWD层 P053 P054 P055 P056 P057 P058 P059 P060 P061 P062 P063 P064 P065 第9章 数仓开发之DWD层 P053 9.6 用户域用户注册事务事实表 9.6.1 主要任务 读…

Facebook主页评分的优化建议

Facebook是全球最大的社交媒体平台之一&#xff0c;它拥有着超10亿的用户&#xff0c;那么在这个竞争激烈的平台上维护和优化你的Facebook主页评分对于增加曝光度以及吸引更多的粉丝和提升品牌形象是非常重要的&#xff0c;下面小编将讲讲Facebook主页评分的优化建议。 1、清楚…

《国产服务器操作系统发展报告(2023)》重磅发布

11月1日&#xff0c;《国产服务器操作系统发展报告&#xff08;2023&#xff09;》&#xff08;以下简称“报告”&#xff09;在 2023 云栖大会上正式发布&#xff0c;开放原子开源基金会理事长孙文龙、中国信息通信研究院副总工程师石友康、阿里云基础软件部副总裁马涛、浪潮信…

MathWorks Matlab R2023b ARM Mac报错 License Manager Error -8

MathWorks Matlab R2023b 23.2.0.2365128 ARM 版本安装激活后出现报错&#xff1a; License Manager Error -8 License checkout failed. License Manager Error -8 Make sure the HostID of the license file matches this machine, and that the HostID on the SERVER line m…

k8s存储卷 PV和PVC

目录 emptyDir存储卷 hostPath存储卷 nfs共享存储卷 PVC 和 PV 生命周期 一个PV从创建到销毁的具体流程如下&#xff1a; 静态pvc 动态pvc 3、定义PVC 4、测试访问 搭建 StorageClass NFS&#xff0c;实现 NFS 的动态 PV 创建 1、在stor01节点上安装nfs&#xff0…

VINS-Mono-后端优化 (二:预积分残差雅可比推导)

文章目录 对位置 δ α \delta\alpha δα 进行求导位置误差 δ α \delta\alpha δα 对平移 P b k w P^{w}_{b_{k}} Pbk​w​ 的求导位置 δ α \delta\alpha δα 对旋转 R w b k R^{b_{k}}_{w} Rwbk​​ 进行求导 对速度 δ β \delta\beta δβ 进行求导速度 δ β…

Vuex介绍

一、Vuex 概述 目标&#xff1a;明确Vuex是什么&#xff0c;应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;Vuex 是一个插件&#xff0c;可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如&#xff1a;购…

创建多层级行索引,创建多层级行索引的DataFrameMultiIndex.from_product()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 创建多层级行索引, 创建多层级行索引的DataFrame MultiIndex.from_product() [太阳]选择题 使用pd.MultiIndex.from_product()&#xff0c;下列输出正确的是&#xff1a; import pandas as pd…

【操作系统】考研真题攻克与重点知识点剖析 - 第 2 篇:进程与线程

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

在Word中优雅的给公式编号,且自动更新

本文适用情景&#xff1a; 使用Word插入公式&#xff1b;需要给公式增加编号&#xff1b;且在正文中引用&#xff0c;支持自动更新序号。 Word自带公式编号 1 Word自带公式编辑器1.1 问题1.2 原因完美解决 2 MathType公式编辑器end: 后记&#xff1a; 1 Word自带公式编辑器 或…

卡尔曼滤波EKF

目录 一、概述 二、卡尔曼滤波的5个公式 三、应用案例&#xff1a;汽车运动 四、应用案例&#xff1a;温度估计 五、总结 一、概述 初学者对于卡尔曼滤波5个公式有点懵&#xff0c;本文先接地气地介绍5个公式&#xff0c;然后举两个常用例子加强理解&#xff0c;同时附有M…

【媒体邀约】媒体宣传——企业成长的催化剂

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传是企业成长的催化剂&#xff0c;它在各种方面对企业的成功和发展起到了关键作用。 1. 曝光和知名度&#xff1a; 媒体宣传可以将企业和其产品或服务推向广泛的受众&#xff0c;…

Vue脚手架学习笔记

视频 Vue脚手架学习笔记 1. 脚手架设置相关内容1.1 各文件的作用1.2 关闭语法检查 2. 组件的使用2.1 单文件组件的使用&#xff08;组件使用的三个步骤&#xff09;2.2 prop配置项&#xff1a;父向子传数据2.2.1 数组方式2.2.2 类型限制2.2.3 默认值、必要性 2.3 ref &#xf…

Hello Qt!

目录 1. 什么是Qt 2. Qt中的模块 3. 下载安装 4. QtCreator 4. Hello Qt 解释 .pro 解释 main.cpp 解释 mainwindow.ui 解释 mainwindow.h 解释 mainwindow.cpp 5. Qt 中的窗口类 5.1 基础窗口类 5.2 窗口的显示 6. Qt 的坐标体系 7. 内存回收 1. 什么是Qt 是一…

评估APP网页小程序代码UI开发H5估价师怎么评估开发精确研发价格?

作为一名应用程序开发评估师&#xff0c;可能涉及到的主要任务是为特定的应用程序提供估算开发成本和所需时间预测。为了为一个应用程序更准确地评估价格&#xff0c;须遵循以下几个步骤&#xff1a; 问: 如何让一个App更好、更精确地评估出价格&#xff1f; 答: 以下是一个可…