LinkedList与链表(一)(非循环单向链表)

news2024/9/28 15:20:57
    • ArrayList的缺陷

通过ArrayList上节课的学习,我们了解到如果ArrayList要删除或插入一个元素,后面的元素都要进行移动,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置的插入和删除操作比较多的场景。因此java集合又引入了ListedList,即链表结构。

    • 链表

2.1链表的结构

链表是一种物理储存上非连续的储存结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。

【注意】
从图中可以看出,链表结构在逻辑上是连续的,但是在物理上是不连续的;
实际中的节点都是在堆上的;
从堆上申请的空间,是按照一定的策略进行分配的,两个节点的储存空间可能是连续的可能是不连续的(链表的优点就是不需要物理上连续的大块空间)。

现实中链表的种类很多,但基本就以下8种情况:

  1. 单向或双向

  1. 带头或者不带头

  1. 循环或者非循环

这3种大的类型再任意搭配,如:单向不带头非循环链表,双向不带头循环链表等。但是我们重点掌握的只有两种:

  • 无头单项非循环链表:结构简单,一般不会用来储存数据,实际中更多的是作为其他数据结构的子结构,但是这种结构在笔试和面试中常见。

  • 无头双向链表:在Java中的集合框架LinkedList底层的实现都是无头双向循环链表。

2.2无头单向非循环链表的实现

MyLinkedList的简单实现

package Demo1;

import java.util.LinkedList;

/**
 * Describe:这里简单实现一下LinkedList
 * User:lenovo
 * Date:2023-01-04
 * Time:16:21
 */
class ListNode {
    public int val;
    public ListNode next;

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

}

public class MyLinkedList {
    ListNode head;

    //为了下面的更好的调试,我们自己创造一个方法,来打印这个链表,但是这个方法并不是有的
    public void display() {
        ListNode cur = head;
        while(cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    //头插法
    public void addFirst(int data) {
        ListNode cur = new ListNode(data);
        cur.next = head;
        head = cur;
    }

    //尾插法
    public void addLast(int data) {
        ListNode cur = head;
        //判断链表是否为空
        if(head == null) {
            head = new ListNode(data);
        }
        //找到链表的最后一个节点
        while(cur.next != null) {
            cur = cur.next;
        }
        ListNode tmp = new ListNode(data);
        cur.next = tmp;
    }

    //任意位置插入,第一个节点为0号下表
    public void addIndex(int index, int data) {
        if(index < 0) {
            throw new ListIndexOutOfException("请检查坐标合法性");
        }
        //如果原链表为空
        if(head == null) {
            head = new ListNode(data);
            return;
        }
        ListNode cur = head;
        ListNode tmp = new ListNode(data);
        int count = 0;
        //如果是头插
        if(index == 0) {
            tmp.next = head;
            head = tmp;
            return;
        }
        //不是头插
        while(cur != null) {
            if(count + 1 == index) {
                tmp.next = cur.next;
                cur.next = tmp;
                return;
            }else {
                count++;
                cur = cur.next;
            }
        }
        if(count != index) {
            throw new ListIndexOutOfException("请检查坐标的合法性");
        }
    }

    //查找关键字key是否在单链表中
    public boolean contains(int key) {
        if(head == null) {
            return true;
        }
        ListNode cur = head;
        while(cur != null) {
            if(cur.val == key) {
                return true;
            }else {
                cur = cur.next;
            }
        }
        return false;
    }

    //删除第一次出现关键字的节点
    public void remove(int key) {
        if(head == null) {
            return;
        }
        ListNode cur = head;
        //第一个节点判断
        if(head.val == key) {
            head = head.next;
            return;
        }
        //其他节点的判断
        while(cur.next != null) {
            if(cur.next.val == key) {
                cur.next = cur.next.next;
                return;
            }else {
                cur = cur.next;
            }
        }
    }

    //删除所有的关键字key的节点
    public void removeAllKey(int key) {
        //链表为空
        if(head == null) {
            return;
        }
        //除了第一个节点,其他节点的判断
        ListNode cur = head;
        while(cur.next != null) {
            if(cur.next.val == key) {
                cur.next = cur.next.next;
            }else {
                cur = cur.next;
            }
        }
        //第一个节点的判断
        if(head.val == key) {
            head = head.next;
        }
    }

    //清除所有节点
    public void clear() {
        head = null;
    }

    //得到单链表的长度
    public int size() {
        int count = 0;
        ListNode cur = head;
        while(cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

}

异常类型

package Demo1;

/**
 * Describe:
 * User:lenovo
 * Date:2023-01-04
 * Time:19:13
 */
public class ListIndexOutOfException extends RuntimeException{
    public ListIndexOutOfException() {}
    public ListIndexOutOfException(String message) {
        super(message);
    }
}

对代码进行测试

import Demo1.MyLinkedList;

import java.util.ArrayList;
import java.util.LinkedList;

/**
 * Describe:
 * User:lenovo
 * Date:2023-01-04
 * Time:15:47
 */
public class Test {
    public static void main(String[] args) {
        MyLinkedList a = new MyLinkedList();
        System.out.println("============头插法============");
        a.addFirst(6);
        a.addFirst(5);
        a.addFirst(4);
        a.addFirst(3);
        a.addFirst(2);
        a.addFirst(1);
        a.display();
        System.out.println("===========尾插法==============");
        a.addLast(7);
        a.addLast(8);
        a.display();
        System.out.println("==========插入任意位置========");
        a.addIndex(0,0);
        a.addIndex(1,1);
        a.addIndex(10,9);
        a.display();
        System.out.println("==========在链表中查找是否包含关键字=======");
        System.out.println(a.contains(0));
        System.out.println(a.contains(99));
        System.out.println("============删除第一个0============");
        a.remove(0);
        a.remove(99);
        a.display();
        System.out.println("===========删除所有的1============");
        a.removeAllKey(1);
        a.removeAllKey(9);
        a.display();
        System.out.println("===========获得链表的长度==========");
        System.out.println(a.size());
        System.out.println("==============清空链表=============");
        a.clear();
        a.display();
    }
}

结果展示

3.单项链表相关习题

我会以博客的形式为大家展现,完成后会将链接放在下面。

希望大家多多鼓励和支持!!!!

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

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

相关文章

Python if __name__ == “__main__“ 用法

文章目录1 前言2 原理3 __name__变量的作用参考1 前言 在很多Python程序中&#xff0c;我们都会遇到if __name__ "__main__"的情况&#xff0c;却不知道为何要这样做 在很多编程语言中&#xff0c;如C、Java等&#xff0c;都需要程序的入口&#xff0c;一般都是ma…

MySql锁机制(全网最全、最详细、最清晰)

1、MySql锁机制 锁机制的作用&#xff1a; 解决因为资源共享&#xff0c;而造成的并发问题。 没有锁机制时&#xff1a; 例如一号用户和二号用户都要去买同一件商品&#xff08;假如这件商品是一件衣服&#xff09;&#xff0c;一号用户手速稍微快了一些&#xff0c;于是就…

从事软件测试需要学自动化么

相信许多对软件测试有过一点了解的人&#xff0c;对自动化都不会感到陌生。我们常常会听到一定软件测试人员一定要学自动化的说法&#xff0c;那么很多人都会有这样的疑问&#xff0c;从事软件测试为什么要学自动化&#xff1f;事实上&#xff0c;如今只会功能测试的从业者往往…

光波导成为AR眼镜迭代新趋势,二维扩瞳几何光波导潜力彰显

关注AR眼镜的朋友可能都会发现&#xff0c;近期新品迭代的一个趋势是持续在小型化、轻量化方向演进。与一年前光学方案主要以BirdBath不同的是&#xff0c;消费级AR眼镜正快速向光波导方案探索和转变。这一点在最近发布的众多新品AR眼镜中就能明显的感受到&#xff0c;以视享G5…

堆排序 TopK 优先级队列的部分源码 JAVA对象的比较

一.堆排序:我们该如何借助堆来对数组的内容来进行排序呢&#xff1f; 假设我们现在有一个数组&#xff0c;要求从小到大进行排序&#xff0c;我们是需要进行建立一个大堆还是建立一个小堆呢&#xff1f; 1)我的第一步的思路就是建立一个小堆&#xff0c;因为每一次堆顶上面的元…

MGRE和ospf的综合运用

目录实验需求知识点实验过程一&#xff0c;在R1 R2 R3中的MGRE搭建二&#xff0c;在R1 R4 R5中的MGRE搭建三&#xff0c;整个内网的ospf协议实验需求 一 题目要求 1&#xff0c;R6为ISP代表运营商&#xff0c;只能配置ip地址&#xff0c;R1-R5环回 代表私有网段 2&#xff0c…

【Linux】顶级编辑器Vim的基本使用及配置

&#x1f451;作者主页&#xff1a;进击的安度因 &#x1f3e0;学习社区&#xff1a;进击的安度因&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux 文章目录一、前言二、vim基本概念三、vim 基本操作1、模式切换2、命令模式3、插入模式4、底行模式四…

[Vue的数据绑定]一.Vue的数据绑定;二.Vue的事件绑定;三.Class和Style的绑定;四.Vue的过滤器;五.Vue脚手架的使用

目录 一.Vue的数据绑定 1.单向数据绑定&#xff1a;将Model绑定到View上&#xff0c;当通过JavaScript代码改变了Model时&#xff0c;View就会自动刷新。不需要进行额外的DOM操作就可以实现视图和模型的联动 &#xff08;1&#xff09;插值表达式&#xff1a;{{ 表达式 }}&am…

pandas 使用

import pandas as pd a [3,7,2] myvar pd.Series(a,index["x","y","z"]) print(myvar["x"]) #结果是3 #给序列赋值index &#xff0c;然后可以根据index找到对应的数 data {"col1": range(-5,0), "col2": r…

半入耳式耳机适合跑步吗、最适合跑步的五款耳机分享

好的跑步耳机可以帮助您跑得更努力、更快和更久。研究发现&#xff0c;听音乐可以提高跑步成绩&#xff0c;尤其是在速度方面。同时&#xff0c;随着音乐锻炼可以提高跑步者的速度并减少精神疲劳&#xff0c;帮助您自信地打破这些束缚。那么目前市面上有哪些无线耳机是适合跑步…

【算法】分治算法(第三章习题解答)

3 分治算法 3.1 设 AAA 是 nnn 个非 000 实数构成的数组, 设计一个算法重新排列数组中的数, 使得负数都排在正数前面. 要求算法使用 O(n)O(n)O(n) 的时间和 O(1)O(1)O(1) 的空间. 算法设计&#xff1a;由于算法要求使用 O(n)O(n)O(n) 的时间和 O(1)O(1)O(1) 的空间&#xff0…

力扣sql入门篇(八)

力扣sql入门篇(八) 1 订单最多的客户 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT customer_number FROM Orders GROUP BY customer_number having count(order_number)(SELECT max(o1.number)FROM (SELECT count(order_number) numberFRO…

电压放大器在超声导波声弹特性的液压管路压力检测中的应用

实验名称&#xff1a;电压放大器在超声导波声弹特性的液压管路压力检测中的应用 研究方向&#xff1a;超声检测 实验目的&#xff1a; 为实现农机装备液压系统的非介入式压力检测&#xff0c;在分析适合压力检测的超声导波声弹敏感模态与激励频率的基础上&#xff0c;搭建了一套…

用埃式筛法来求解素数。————C++

目录埃式筛法埃式筛法求解某一个数字包含的所有素数数组Code运行结果埃式筛法判断某一个数字是否为素数Code运行结果埃式筛法 首先要了解什么式埃式筛法之前&#xff0c;需要知道一个定理。 就是素数的整数倍一定不是素数。 了解了这个就基本大概懂了埃式筛法。 首先初始化…

C语言线性表实现:顺序表

文章目录&#xff1a;概念理解&#xff1a;1. 动态顺序表结构体&#xff1a;2. 顺序表动态初始化&#xff1a;3. 顺序表扩容&#xff1a;4. 插入&#xff1a;5. 删除&#xff1a;6. 按位序查找&#xff1a;7. 按值查找&#xff1a;8. 输出顺序表&#xff1a;9. 判断顺序表是否相…

UniSCA漏洞优先级排序

当谈到开源漏洞时&#xff0c;我们会发现它们似乎永远处于增长状态。事实上&#xff0c;UniSCA的开源风险报告显示&#xff0c;与2021年同期相比&#xff0c;2022年前9个月添加到UniSCA漏洞数据库中的开源软件漏洞数量增长了33% 。然而&#xff0c;虽然有些漏洞会带来严重的业务…

Altium Designer 20 凡亿教育视频学习-04

第四部分学习 unknow pin错误原因 将原理图导入到PCB时会出现问题 管脚未使用报错 导入PCB器件全部绿 删掉下面的紫红色框架即可&#xff08;Sheet2&#xff09; 视频讲的方法是&#xff1a;一开始把所有的规则删掉&#xff0c;只保留电气规则 板子大小评估-把器件聚集在一…

16---实现权限菜单管理(一)

1、实现角色管理 建role表 USE management; DROP TABLE IF EXISTS role;CREATE TABLE role (id int(11) NOT NULL AUTO_INCREMENT COMMENT id,name varchar(50) DEFAULT NULL COMMENT 名称,description varchar(255) DEFAULT NULL COMMENT 描述,PRIMARY KEY (id) ) ENGINEInn…

活动星投票最美空姐网络评选微信的投票方式线上免费投票

如何进行“最美空姐”的投票活动_投票小程序投票_投票助力方式大家在选择投票小程序之前&#xff0c;可以先梳理一下自己的投票评选活动是哪种类型&#xff0c;目前有匿名投票、图文投票、视频投票、赛事征集投票等。我们现在要以“最美空姐”为主题进行一次投票活动&#xff0…

Docker 三剑客

Docker 三剑客包括Docker Machine、Docker Compose、Docker Swarm。 1. Docker Machine 1.1 简介 Docker Machine 是 Docker 官方三剑客项目之一&#xff0c;使用它可以在多个平台上快速安装部署Docker环境&#xff0c;还可以在短时间内快速构建起一套Docker主机集群。 Do…