【数据结构】LinkedList与链表

news2024/11/16 13:34:08

作者:✿✿ xxxflower. ✿✿
博客主页:xxxflower的博客
专栏:【数据结构】篇
语录:⭐每一个不曾起舞的日子,都是对生命的辜负。⭐

文章目录

  • ✿1.ArrayList的缺陷
  • ✿2.链表
    • 2.1链表的概念及结构
    • 2.2链表的模拟实现
      • MySingleList
  • ✿3.LinkedList
    • 3.1LinkedList的模拟实现
      • MyLinkedList
  • ✿4.LinkedList的使用
    • 4.1 什么是LinkedList
    • 4.2LinkedList的使用
  • ✿5.ArrayList 和 LinkedList

✿1.ArrayList的缺陷

ArrayList的底层是一段连续空间的数组,在ArrayList位置任意位置插入或者删除元素时,就需要将后续元素整体往前或者往后移动,时间复杂度为O(n),效率较低。所以ArrayList不适合做任意位置插入和删除比较多的场景。因此,java集合中又引入了LinkList,即链表结构。
在这里插入图片描述

✿2.链表

2.1链表的概念及结构

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

  • 由上图可得,链式结构在逻辑上是连续的,但是在物理上不一定连续。如图:
    在这里插入图片描述

  • 现实中的节点一般都是从堆上申请出来的。

  • 从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续。
    实际中链表的结构非常多样:
    在这里插入图片描述
    我们需要重点学习的有:

  • 单向非循环无头结点链表

结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

  • 无头双向链表

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

2.2链表的模拟实现

MySingleList

使用内部类定义一个节点类。
在这里插入图片描述在这里插入图片描述

打印链表:
1.为了保证head的值不变,定义一个cur
当cur != null(循环条件)时走完整个链表。
2.打印cur.val
3.cur = cur.next.

 public void display(){
        ListNode cur = this.head;
        while(cur != null){
            System.out.println(cur.val + " ");
            cur = cur.next;
        }
    }

如何得到链表的长度?
1.定义一个计数器count
2.当cur!=null时count++;
3.cur = cue.next;

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

头插法:
1.根据形参的数据创建一个节点
2.node.next = this.head; head = node;
在这里插入图片描述

public void addFirst(int data){
        ListNode node = new ListNode(data);
           node.next = head;
           head = node;
    }

尾插法:
1…根据形参的数据创建一个节点node
1.找到尾部。定义一个cur。cur = this.head;
当cur.next == null时,即找到了尾部。
3.判断链表是否为空
4.将节点的node给尾部的next
在这里插入图片描述

 public void addLast(int data){
        ListNode node = new ListNode(data);
        ListNode cur = this.head;
        if(cur == null){
            this.head = node;
        }else{
            while(cur.next != null){
                cur = cur.next;
            }
            cur.next = node;
        }
    }

任意位置插入,第一个数据节点为0号下标:
首先判断index位置是否合法。
分三种情况,头插,尾插和中间插入
1.走index-1步,找到cur
2.ListNode node = new ListNode();
node.next = cur.next;1️⃣
cur.next = node;2️⃣
在这里插入图片描述

//任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        if(index < 0 || index > this.size()){
            System.out.println("index位置不合法!");
            throw new IndexWrongfulExpection("index位置不合法!");
        }
        if(index == 0){
            addFirst(data);
            return;
        }
        if(index ==this.size()){
            addLast(data);
            return;
        }
        ListNode node = new ListNode(data);
        ListNode cur = this.head;
        while(index-1 != 0){
            cur = cur.next;
            index--;
        }
        node.next = cur.next;
        cur.next = node;
    }

查找是否包含关键字key是否在单链表当中:
1.判断链表是否为空?
2.写一个循环遍历数组找到cur.val == key

 public boolean contains(int key){
        if(this.head == null){
            System.out.println("链表为空!");
            return false;
        }
        ListNode cur = this.head;
        while(cur != null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

删除第一次出现关键字为key的节点
1.判断链表是否为空??
2.如果删除的是头结点??
3.写一个函数,封装起来,用于查找key的index的前一个值
4.删除
在这里插入图片描述

public void remove(int key){
        if(this.head == null){
            System.out.println("链表为空!");
            return;
        }
        if(this.head.val == key){
            this.head = this.head.next;
            return;
        }
        ListNode cur = findPrevOfKey(key);
        if(cur == null){
            System.out.println("没有你要删除的数字!");
            return;
        }
        ListNode del = cur.next;
        cur.next = del.next;
    }
    private ListNode findPrevOfKey(int key){
        ListNode cur = this.head;
        while(cur.next != null){
            if(cur.val == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }

//删除所有值为key的节点

  1. 链表是否为空??
  2. 如何删除?定义一个cur = head.next;再定义一个prev作为cur的前驱。
  3. 遍历链表。如果cur.val == key;prev.next = cur.next; cur = cur.next;
  4. 如果cur != key;prev = cur;cur = cur.next;
  5. 以上的方法不能解决头结点是key的情况,所以在需要判断一下头结点位key的情况下做以处理?
    在这里插入图片描述
//删除所有值为key的节点
    public void removeAllKey(int key){
        if(this.head == null){
            System.out.println("链表为空!");
            return;
        }
        ListNode cur = this.head.next;
        ListNode prev = head;
        while(cur != null){
            if(cur.val == key){
                prev.next = cur.next;
                cur = cur.next;
            }else{
                prev = cur;
                cur = cur.next;
            }
        }
        if(this.head.val == key){
            this.head = this.head.next;
        }
    }

到这里我们对单链表就有一定的认识啦~
在这里插入图片描述

✿3.LinkedList

如图,为双向无头循环链表下面我们以此为例来实现双链表的操作。
在这里插入图片描述

3.1LinkedList的模拟实现

MyLinkedList

首先使用内部类创建一个ListNode:

static class ListNode{
        public int val;
        public ListNode prve;
        public ListNode next;
        public ListNode(int val){
            this.val = val;
        }
    }

头插法:
在这里插入图片描述

//头插法
    public void addFirst(int data){
        ListNode node = new ListNode(data);
        if(this.head == null){
            head = node;
            tail = node;
        }else {
            head.prve = node;
            node.next = head;
            head = this.head.next;

        }
    }

尾插法:
在这里插入图片描述

//尾插法
    public void addLast(int data){
        ListNode node = new ListNode(data);
        if(this.head == null){
            this.head = node;
            this.tail = node;
        }
        node.prve = tail;
        tail.next = node;
        tail = node;
    }

任意位置插入,第一个数据节点为0号下标
在这里插入图片描述

  //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        //1.判断index位置的合法性
        if(index < 0 || index > size()){
            System.out.println("index位置不合法!");
            throw new IndexWrongfulExpection("index位置不合法!");
        }
        //2.判断特殊位置
        if(index == 0){
            addFirst(data);
            return ;
        }
        if(index == size()){
            addLast(data);
            return ;
        }
        //3.找到index位置节点的地址
        ListNode node = new ListNode(data);
        ListNode cur = findIndexListNode(index);
        //4.修改指向
        node.next = cur;
        node.prve = cur.prve;
        cur.prve.next = node;
        cur.prve = node;

    }
    public ListNode findIndexListNode(int index){
        ListNode cur = this.head;
        while(index != 0){
            cur = cur.next;
            index--;
        }
        return cur;
    }

查找是否包含关键字key是否在单链表当中

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

//删除第一次出现关键字为key的节点
在这里插入图片描述

public void remove(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                    if(head != null){
                        head.prve = null;
                    }else{
                        tail = null;
                    }
                }else{
                    cur.prve.next = cur.next;
                    if( cur.next != null){
                        cur.next.prve = cur.prve;
                    }else{
                        this.tail = cur.prve;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

删除所有值为key的节点:此处和删除首个关键字值的代码大同小异。只需要遍历完整个链表即可。

  //删除所有值为key的节点
    public void removeAllKey(int key) {
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                    if(head != null){
                        head.prve = null;
                    }else{
                        tail = null;
                    }
                }else{
                    cur.prve.next = cur.next;
                    if( cur.next != null){
                        cur.next.prve = cur.prve;
                    }else{
                        this.tail = cur.prve;
                    }
                }
            }
            cur = cur.next;
        }
    }

双链表和单链表的部分函数写法思路是一样的。
在这里插入图片描述

✿4.LinkedList的使用

4.1 什么是LinkedList

LinkedList的底层是双向链表结构(链表后面介绍),由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
在集合框架中,LinkedList也实现了List接口,具体如下:
在这里插入图片描述
说明:

  1. LinkedList实现了List接口
  2. LinkedList的底层使用了双向链表
  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)

4.2LinkedList的使用

详情见帮助手册。
这里偷个懒哈哈
在这里插入图片描述

✿5.ArrayList 和 LinkedList

在这里插入图片描述

ArrayList 和 LinkedList 的区别???

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

aws eks 集群container runtime升级容器管理工具的切换

参考资料 https://cloud-atlas.readthedocs.io/zh_CN/latest/kubernetes/debug/crictl.htmlhttps://zhuanlan.zhihu.com/p/562014518 container runtime Low-Level和High-Level容器运行时。runc、lxc、lmctfy、Docker&#xff08;容器&#xff09;、rkt、cri-o。每一个都是为…

springboot simple (12) springboot RabbitMQ

这里首先简单的介绍了RabbitMQ &#xff0c;然后实现了springboot集成RabbitMQ &#xff0c;包含两个工程&#xff1a; 1 Producer 生产者 2 Consumer 消费者 1 RabbitMQ 简介 AMQP &#xff1a;Advanced Message Queue&#xff0c;高级消息队列协议。 RabbitMQ 是一个由 Erl…

智能大屏兴起,酷开科技赋能营销战略!

随着科技的发展&#xff0c;智能大屏的功能与技术都在日新月异的快速更迭&#xff0c;年轻消费群体也对大尺寸智能大屏表现出了特别的偏爱&#xff0c;以前说到看视频、网上购物、阅读书籍时&#xff0c;人们第一时间就会想到手机&#xff0c;但随着智能大屏的出现&#xff0c;…

商用设计素材库,设计师必备。

免费、商用设计素材网站。 1、菜鸟图库 https://www.sucai999.com/?vNTYxMjky站内平面海报、UI设计、电商淘宝、免抠、高清图片、样机模板等素材非常齐全。还有在线抠图、CDR版本转换功能&#xff0c;能有效的为设计师节省找素材时间&#xff0c;提高工作效率。网站素材都能免…

LeetCode链表经典题目(二)

1. LeetCode203. 移除链表元素 2. LeetCode707.设计链表 3. LeetCode206. 反转链表 4. LeetCode24. 两两交换链表中的节点​ 5. LeetCode19. 删除链表的倒数第 N 个结点 6. LeetCode面试题 02.07. 链表相交 7. LeetCode142. 环形链表 II​ 1. LeetCode203. 移除链表元素 …

基于同豪的道路桥梁设计方案如何实现数字化交付(web发布)

0序&#xff1a; 当下有部分设计人员除了使用Revit、Microstation之外也使用过程的同豪软件进行道路桥梁的BIM建模。如何对同豪的BIM模型进行数字化交付呢&#xff1f; 1数据导出为FBX 具体导出过程可以参考&#xff1a; 数据的导出只要按步骤导出就行&#xff0c;非常简单…

2023最让人期待的日历!每个IT技术人必备

一转眼&#xff0c;2022年已经要接近尾声了..... 这一年的你过的怎么样呢&#xff1f;相比上一年的自己有什么变化呢&#xff1f; 凡是过往皆为序章&#xff0c;所有将来皆为可盼&#xff01;在2023年即将到来之际给大家推荐一本非常适合IT技术人的日历&#x1f449;「小滴日历…

python—you-get下载工具、wget下载工具

目录 wget you-get wget wget工具下载&#xff1a;GNU Wget 1.21.3 for Windows wget工具见&#xff1a;python-外部程序的调用os库、subprocess 模块_觅远的博客-CSDN博客_python外部库调用调出 you-get you-get是一款实用的网站视频下载工具。可以很轻松的下载到网络上…

极限学习机ELM回归预测(MATLAB代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

【数据结构与算法】第十七篇:图论万字解析(进阶篇)

&#x1f440;作者简介&#xff1a;大家好&#xff0c;我是 快到碗里来~ &#x1f6a9;&#x1f6a9; 个人主页&#xff1a;快到碗里来~ 支持我&#xff1a;点赞关注~不迷路&#x1f9e1;&#x1f9e1;&#x1f9e1; ✔系列专栏&#xff1a;数据结构与算法⚡⚡⚡ (❁◡❁)励志格…

代码随想录算法训练营第十一天(栈与队列)| 20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值

代码随想录算法训练营第十一天&#xff08;栈与队列&#xff09;| 20. 有效的括号&#xff0c;1047. 删除字符串中的所有相邻重复项&#xff0c;150. 逆波兰表达式求值 20. 有效的括号 讲完了栈实现队列&#xff0c;队列实现栈&#xff0c;接下来就是栈的经典应用了。 大家先…

激发原创力量,逐梦数智未来 | 麒麟信安闪耀openEuler Summit 2022

[中国&#xff0c;北京&#xff0c;2022年12月29日]由欧拉开源社区发起并联合华为、麒麟信安、麒麟软件、统信软件等伙伴&#xff0c;共同举办的openEuler Summit 2022于线上举行。 会上&#xff0c;开放原子开源基金会宣布openEuler项目群成立&#xff1b;同时&#xff0c;新…

CVPR 2021|Deep-SfM-Revisited:DeepLearn+经典SfM流程

&#x1f3c6;前言&#xff1a;文章回顾了深度学习在SfM中的应用&#xff0c;并提出了一种新的深度两视图SfM框架。该框架结合了深度学习和经典SfM几何算法的优点。在各个数据集上取得较好的结果。 文章目录解决的问题基本流程实施细节光流估计相机位姿估计尺度不变的深度估计损…

关于安科瑞电力监控系统在电力工程中的应用与对策

摘要&#xff1a;随着经济的发展&#xff0c;能源消耗速度正不断加快&#xff0c;因此我国提出了绿色可持续发展战略&#xff0c;要求在发展建设中以节能为主&#xff0c;不断减少资源能耗&#xff0c;而电能便是首要控制内容。如今我国为电能使用&#xff0c;对计量表进行了优…

《PyTorch深度学习实践》完结合集-P4反向传播作业

二次函数的反向传播 代码&#xff1a; import torch x_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0] w1 torch.Tensor([1.0]) w1.requires_grad True #定义要进行反向传播 w2 torch.Tensor([1.0]) w2.requires_grad True b torch.Tensor([1.0]) b.requires_grad T…

PHP结课报告-简单的点菜系统(完整版,附源码与数据库)

1 系统背景及意义 1.1系统开发背景介绍 餐饮业在我国有着悠久的发展历史&#xff0c;是与人民生活密切相关的 行业之一&#xff0c;同时也是我国经济增长的新亮点&#xff0c;在 2010 年全国餐饮零 售总额高达 15913 亿元&#xff0c;实际增长约 14.3。在信息系统相对普及的 今…

项目经理通过甘特图编制项目计划的方法

项目有个特征叫 渐进明晰 &#xff0c;指一个项目不可能一开始就能想到最后交付成果的全部细节&#xff0c;项目最终的交付成果到底长啥样是随着项目的推进慢慢变得清晰的&#xff0c;而这个变化的过程不仅需要项目经理的经验与能力&#xff0c;还需要借助项目管理工具的帮助。…

一文讲清「敏捷路线图」,从此不再掉入瀑布陷阱

尽管许多组织和团队声称自己非常敏捷&#xff0c;但他们仍在使用瀑布的方式规划产品。为什么会这样&#xff1f;我们该如何改变这种「错误敏捷」&#xff1f; 原则上&#xff0c;践行敏捷开发很简单&#xff1a;构建一个增量&#xff1b;测试这个增量&#xff1b;了解需要改变…

webdriver的尝试:四 【移动端的使用appium-定位与获取代码】

文章目录界面的简单认识和使用参考我们前面使用webdriver可以实现&#xff1a;使用代码&#xff0c;自动化打开浏览器及指定页面&#xff0c;定位元素&#xff0c;获取内容或者模仿操作那么使用移动端&#xff0c;依然需要实现定位与操作 主要就是在appium inspector上进行操作…

开源全球公司贡献 49 名,涛思数据荣登 2022 中国开发者影响力年度榜单

12 月 28 日&#xff0c;CSDN 在北京举行 “2022 中国开发者影响力盛典暨 CSDN 企业生态汇”活动&#xff0c;同时正式发布 2022 中国开发者影响力年度榜单。本次公布的榜单主要包括年度开源贡献企业、年度开源影响力项目、年度开发者社区、年度数字化创新企业、年度优秀雇主企…