数据结构:LinkedList与链表—无头双向链表(二)

news2025/1/8 9:49:43

目录

一、什么是LinkedList?

二、LinkedList的模拟实现

1、display()方法

2、addFirst(int data)方法

3、addLast(int data)方法

4、addIndex(int index,int data)方法

5、contains(int key)方法

6、remove(int key)方法

7、removeAllKey(int key)方法

8、size()方法

9、clear()方法

10、完整代码 

三、LinkedList的使用

1、LinkedList的构造

(1)LinkedList()无参构造

(2)LinkedList(Collection c)利用Collection进行构造

2、LinkedList的常用方法

3、LinkedList的遍历

(1)for each 遍历

(2)使用迭代器遍历-- 正向遍历

(3)使用反向迭代器-- 反向遍历

四、ArrayList和LinkedList的区别


一、什么是LinkedList?

LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。同时,LinkedList也实现了List接口

二、LinkedList的模拟实现

1、display()方法

打印单链表

2、addFirst(int data)方法

模拟实现一个Ilist接口

依旧是创建一个MyLinkedList类实现IList接口,在类中创建一个结点,结点当中设置一个变量存入数据一个前驱和一个后继。然后在创建一个头结点和一个尾结点(当然我们这里的结点依然只是一个引用,一个用来存储第一数据,一个用来存储最后一个数据,并不是所谓固定的头结点)

头插法

我们需要将要插入元素的后继改成原先的头节点,然后将原先头结点的前驱改成要插入的结点,最后将头节点的位置变为要插入的结点

 

3、addLast(int data)方法

尾插法

我们将要插入元素的前驱改成尾结点,将为结点的后继改成要插入的结点,最后将尾结点变成要插入的结点

4、addIndex(int index,int data)方法

任意位置插入 , 第一个数据节点为 0 号下标

在这我们需要找到要插入位置的原本节点,令原本节点的下一个结点的前驱设置为要插入的结点,将要插入的结点的后继设置为原本结点的下一个结点,之后再将原本结点的后继设置为要插入的结点,将要插入结点的前驱设置为原本结点

5、contains(int key)方法

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

6、remove(int key)方法

 删除第⼀次出现关键字为 key 的结点

我们先找到key的结点将这个删除结点的前一个结点的后继改为这个删除结点的后继结点,再将这个删除结点的后一个结点的前驱改为要删除结点的前驱结点

当我们要删除的结点为头结点时,我们只需要将头结点变为下一个结点,再将这个新的头结点的前驱置为空 

当要删除的结点为尾结点时,我们只需要将尾结点向前移动,同时将新尾结点的后继置为空(但其实我们可以不用写出这步置为空,一会我们来看我们的代码就明白了) 

7、removeAllKey(int key)方法

删除所有值为 key 的节点

对与这一方法如果已经明白了上面的操作了就非常简单了,因为这时要我们删除所有的key结点,在上面我们是只删除一次就结束了,既然要删除所有的我们只需要将return删除即可

8、size()方法

得到单链表的长度 

9、clear()方法

清空链表

10、完整代码 

IList接口

public interface IList {

    //头插法
   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 display();

    //清空链表
    void clear();
}

MyLinkedList

public class MyLinkedList implements IList {

    static class ListNode {
        private int val;
        private ListNode prev;
        private ListNode next;

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

    public ListNode head;
    public ListNode last;



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

    @Override
    public void addFirst(int data) {
        ListNode node = new ListNode(data);
        if(head == null){
            this.head = node;
            this.last = node;
        }
        node.next = this.head;
        this.head.prev = node;
        this.head = node;
    }

    @Override
    public void addLast(int data) {
        ListNode node = new ListNode(data);
        if(head == null){
            this.head = node;
            this.last = node;
        }
        this.last.next = node;
        node.prev = this.last;
        this.last = node;

    }

    @Override
    public void addIndex(int index, int data) {
        try{
            check1(index);
            if(index == 0){
                addFirst(data);
                return;
            }
            if(index == size()){
                addLast(data);
                return;
            }
            ListNode cur = findNode(index);
            ListNode node = new ListNode(data);
            cur.next.prev = node;
            node.next = cur.next;
            cur.next = node;
            node.prev = cur;


        }catch (Illegality e){
            e.printStackTrace();
        }
    }
    public void check1(int index) throws Illegality{
        if( index < 0 || index > size()){
            throw new Illegality("index不合法");
        }
    }

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

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

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

    @Override
    public void removeAllKey(int key) {
        ListNode cur = this.head;
        while(cur != null ){
            if(cur.val == key){
                if( cur == this.head){
                    this.head = cur.next;
                    if(this.head != null){
                        this.head.prev = null;
                    }
                }else{
                    cur.prev.next = cur.next;
                    if(cur == this.last){
                        this.last = cur.prev;
                    }else{
                        cur.next.prev = cur.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }


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


    @Override
    public void clear() {
        ListNode cur = head;
        while(cur != null){
            ListNode curN = cur.next;
            cur.prev = null;
            cur.next = null;
            cur = curN;
        }
        this.head = null;
        this.last = null;
    }
}

异常

public class Illegality extends RuntimeException {
    public Illegality(String message){
        super(message);
    }
}

主函数

public class Test {
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
    }
}

三、LinkedList的使用

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

1、LinkedList的构造

(1)LinkedList()无参构造

(2)LinkedList(Collection<? extends E> c)利用Collection进行构造

2、LinkedList的常用方法

方法解释
boolean add(E e)尾插e
void add(int index, E element)将e插入到 index 位置
boolean addAll(Collection<? extends E> c)尾插c中的元素
E remove(int index)删除 index 位置元素
boolean remove(object o)删除遇到的第一个o
E get(int index)获取下标 index 位置元素
E set(int index, E element)将下标 index 位置元素设置为 element
void clear()清空
boolean contains(Object o)判断o是否在线性表中
int indexof(object o)返回第一个o所在下标
int lastIndexof(Object o)返回最后一个o的下标
List<E> subList(int fromindex, int tolndex)截取部分 list

这里这些常用方法有些是我们上面没有实现的,但是在顺序表那篇文章中我都进行了讲解,大家可以去看这篇文章

数据结构:ArrayList与顺序表

3、LinkedList的遍历

除了我经常使用的sout方法外还有三种方法

(1)for each 遍历

(2)使用迭代器遍历-- 正向遍历

(3)使用反向迭代器-- 反向遍历

四、ArrayList和LinkedList的区别

好了到目前为止我们已经学完了顺序表和链表了,那么他们之间有什么区别呢?

不同点ArrayListLinkedList
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持0(1)不支持:O(N)
头插需要搬移元素,效率低O(N)只需修改引用的指向,时间复杂度为0(1)
插入空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁

好了,今天的讲解就到这里了,还请大家多多关注,我们下一篇再见!

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

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

相关文章

基于SpringBoot实现的保障性住房管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

【Linux】硬链接和软连接(符号连接)

目录 硬链接 软连接 硬链接和软连接的区别 硬链接 ln根据linux系统分配给文件inode(ls -li)进行建立&#xff0c;没办法跨越文件系统 格式&#xff1a;ln 被链接的文件(源文件) 生成的链接文件(目标文件) 1) 硬链接的属性 - 相当于生成一个副本 起别名 2) 修改内容都变化…

多目标优化算法——基于聚类的不规则Pareto前沿多目标优化自适应进化算法(CA-MOEA)

基于聚类的不规则Pareto前沿多目标优化自适应进化算法&#xff08;CA-MOEA&#xff09; 一、算法简介 简介&#xff1a; 现有的多目标进化算法&#xff08;moea&#xff09;在具有规则Pareto前沿且Pareto最优解在目标空间上连续分布的多目标优化问题&#xff08;MOPs&#xff…

基于SpringBoot的乐器商城购物推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

【vba源码】自动获取汇率

Hi&#xff0c;大家好&#xff01; 没有想到今天居然是腊八&#xff0c;过了腊八就是年&#xff0c;离过年越来越近了&#xff0c;那在这里给大家就拜个年&#xff0c;希望大家在新的一年都有好事发生。 最近在弄点小项目&#xff0c;在项目遇到了一个汇率计算的问题&#xff…

JavaEE初阶——计算机工作原理

一、什么是JavaEE JavaEE&#xff08;Java Platform&#xff0c;Enterprise Edition&#xff09;是sun公司&#xff08;2009年4月20日甲骨文将其收购&#xff09;推出的企业级应用程序版本。这个版本以前称为 J2EE。能够帮助我们开发和部署可移植、健壮、可伸缩且安全的服务器…

【Unity3D】AB包加密(AssetBundle加密)

加密前&#xff1a; 加密后&#xff0c;直接无法加载ab&#xff0c;所以无法正常看到ab内容。 using UnityEngine; using UnityEditor; using System.IO; public static class AssetBundleDemoTest {[MenuItem("Tools/打包!")]public static void Build(){//注意:St…

数据库语句学习

WHERE AND: 请编写 SQL 语句&#xff0c;从 courses 表中&#xff0c;选取课程名为 Web 或者 Big Data 的课程信息&#xff0c;如果这两门课程存在&#xff0c;请将这两门课程的信息全部返回。 SELECT * FROM courses where name in (Web,Big Data) -- 等同于 -- WHERE name …

“AI智慧语言训练系统:让语言学习变得更简单有趣

大家好&#xff0c;我是你们的老朋友&#xff0c;一个热衷于探讨科技与教育结合的产品经理。今天&#xff0c;我想和大家聊聊一个让语言学习变得不再头疼的话题——AI智慧语言训练系统。这个系统可是我们语言学习者的福音&#xff0c;让我们一起来揭开它的神秘面纱吧&#xff0…

Postman接口测试05|实战项目笔记

目录 一、项目接口概况 二、单接口测试-登录接口&#xff1a;POST 1、正例 2、反例 ①姓名未注册 ②密码错误 ③姓名为空 ④多参 ⑤少参 ⑥无参 三、批量运行测试用例 四、生成测试报告 1、Postman界面生成 2、Newman命令行生成 五、token鉴权&#xff08;“…

使用Locust对MongoDB进行负载测试

1.安装环境 pip install pymongo locust 2.设置测试环境 开启MongoDB服务 打开Navicat&#xff0c;新建MongoDB连接 新建test数据库和sample集合 3.编写脚本 load_mongo.py # codingutf-8 from locust import User, task, between, events from pymongo import MongoClie…

【微服务】3、配置管理

微服务配置管理 已掌握的微服务组件及配置管理问题引出 已掌握注册中心、Openfan、远程调用、负载均衡、网关等组件&#xff0c;具备微服务开发能力&#xff0c;但仍存在其他问题待解决。微服务和网关存在大量配置文件&#xff0c;其中包含很多重复配置&#xff0c;如数据库、日…

【Notepad++】Notepad++如何删除包含某个字符串所在的行

Notepad如何删除包含某个字符串所在的行 一&#xff0c;简介二&#xff0c;操作方法三&#xff0c;总结 一&#xff0c;简介 在使用beyoundcompare软件进行对比的时候&#xff0c;常常会出现一些无关紧要的地方&#xff0c;且所在行的内容是变化的&#xff0c;不方便进行比较&…

计算机网络——期末复习(7)期末试卷样例3

一、辨析题&#xff08;共4小题&#xff0c;每小题5分&#xff0c;共20分&#xff09; 1.差错检测是保障网络正常通信的一项重要措施&#xff0c;有多种差错检测算法&#xff08;技术&#xff09;&#xff0c; &#xff08;1&#xff09;以太网和IP协议各自采用的差错校验算法…

STM32-笔记34-4G遥控灯

4G接线 一、项目需求 服务器通过4G模块远程遥控开关灯。 二、项目实现 复制项目文件夹38-wifi控制风扇项目 重命名为39-4G遥控点灯 打开项目文件 加载文件 main.c #include "sys.h" #include "delay.h" #include "led.h" #include "ua…

游戏引擎学习第77天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾昨天的 bug 今天我们继续开发进度&#xff0c;进行调试昨天代码的问题&#xff0c;主要是关于如何跟踪玩家和敌人在世界中的高度位置。虽然我们做的是一款 2D 游戏&#xff0c;但我们希望能够处理多层的房间&#xff0c;玩家…

STM32完全学习——使用定时器1精确延时

一、定时器的相关配置 首先一定要是递减定时器&#xff0c;递增的不太行&#xff0c;控制的不够准确&#xff0c;其次在大于10微秒的延时是非常准确的&#xff0c;小于的话&#xff0c;就没有那没准&#xff0c;但是凑合能用。误差都在一个微秒以内。使用高级定时器也就是时钟…

aardio —— 虚表 —— 模拟属性框

写了个简单的属性框例程&#xff0c;抛砖引玉&#xff0c;期待你做出更丰富强大的功能。 本例演示&#xff1a;折叠子行、选择框、输入文本、输入数值、下拉选择、选择图片、选择颜色、选择字体等功能。 只有想不到&#xff0c;没有做不到&#xff0c;发挥你的想象力吧。 imp…

[微服务]redis主从集群搭建与优化

搭建主从集群 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离。 1. 主从集群结构 下图就是一个简单的Redis主从集群结构&#xff1a; 如图所示&#xff0c;集群中有一个master节点、两个s…

设计模式 行为型 观察者模式(Observer Pattern)与 常见技术框架应用 解析

观察者模式&#xff08;Observer Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时&#xff0c;会通知所有观察者对象&#xff0c;使它们能够自动更新。 一…