篇章六 数据结构——链表(二)

news2025/6/4 5:23:33

目录

1. LinkedList的模拟实现

1.1 双向链表结构图​编辑

1.2 三个简单方法的实现

1.3 头插法

1.4 尾插法

1.5 中间插入

1.6 删除 key

1.7 删除所有key

1.8 clear

2.LinkedList的使用

2.1 什么是LinkedList

5.2 LinkedList的使用

 1.LinkedList的构造

2. LinkedList的其他常用方法介绍

3.LinkedList的遍历33.

5.3 ArrayList 和 LinkedList的区别


1. LinkedList的模拟实现

1.1 双向链表结构图

1.2 三个简单方法的实现

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

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

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

此处和单链表一样,不在赘述。

1.3 头插法

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

1.4 尾插法

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

1.5 中间插入

@Override
public void addIndex(int index, int data) {
    int len = size();
    if (index < 0 || index > len) {
        return;
    }

    if (index == 0) {
        addFirst(data);
        return;
    }

    if (index == len) {
        addLast(data);
        return;
    }

    // 中间插入
    ListNode node = new ListNode(data);
    ListNode cur = findIndex(index);
    node.next = cur;
    cur.prev.next = node;
    node.prev = cur.prev;
    cur.prev = node;
}
private ListNode findIndex(int index) {
    ListNode cur = head;
    while (index != 0) {
        cur = cur.next;
        index--;
    }
    return cur;
}

此处直接找到 index 位置即可,不需要找 index - 1,因为有 prev

1.6 删除 key

@Override
    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.prev = null;
                    }
                } else {
                    cur.prev.next = cur.next;
                    if (cur.next == null) {
                        last = last.prev;
                    }else {
                        cur.next.prev = cur.prev;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

注意:

1.此处最关键的代码:

        cur.prev.next = cur.next;

        cur.next.prev = cur.prev;

2.但是很显然解决不了头节点和尾节点,需要条件语句单独处理

3.特殊情况:

        只有一个节点的链表,且为key值

        需要加上判断逻辑:

                    if (head != null) {
                        head.prev = null;
                    }

1.7 删除所有key

@Override
    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.prev = null;
                    }
                } else {
                    cur.prev.next = cur.next;
                    if (cur.next == null) {
                        last = last.prev;
                    }else {
                        cur.next.prev = cur.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }

注意:

        很显然将 删除key代码中的 return;删除即可

1.8 clear

    @Override
    public void clear() {
        ListNode cur = head;

        while (cur != null) {
            ListNode curNext = cur.next;
            cur.prev = null;
            cur.next = null;
            cur = curNext;
        }
        head = null;
        last = null;
    }

2.LinkedList的使用

2.1 什么是LinkedList

LinkedList 的官方文档

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

在集合框架中,LinkedList也实现了List接口,具体如下:

【说明】

  1. LinkedList实现了List接口

  2. LinkedList的底层使用了双向链表

  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问

  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)

  5. LinkedList比较适合任意位置插入的场景

5.2 LinkedList的使用

 1.LinkedList的构造

2. LinkedList的其他常用方法介绍

3.LinkedList的遍历33.

 public static void main(String[] args) {
        LinkedList<Integer> linkedList2 = new LinkedList<>();

        linkedList2.add(1);
        linkedList2.addLast(3);
        linkedList2.addLast(4);
        linkedList2.addLast(5);
        System.out.println(linkedList2);

        System.out.println("=========ListIterator=========");
        ListIterator<Integer> listIterator = linkedList2.listIterator(linkedList2.size());
        while (listIterator.hasPrevious()) {
            System.out.print(listIterator.previous() + " ");
        }
        System.out.println();

        System.out.println("=========ListIterator=========");
        ListIterator<Integer> listIterator1 = linkedList2.listIterator();
        while (listIterator1.hasNext()) {
            System.out.print(listIterator1.next() + " ");
        }
        System.out.println();

        System.out.println("=========Iterator=========");
        Iterator<Integer> iterator = linkedList2.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();

        System.out.println("=========for each=========");
        for (Integer x : linkedList2) {
            System.out.print(x + " ");
        }
        System.out.println();

        System.out.println("=========for=========");
        for (int i = 0; i < linkedList2.size(); i++) {
            System.out.print(linkedList2.get(i) + " ");
        }
        System.out.println();


    }

5.3 ArrayList 和 LinkedList的区别

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

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

相关文章

吴恩达MCP课程(3):mcp_chatbot

原课程代码是用Anthropic写的&#xff0c;下面代码是用OpenAI改写的&#xff0c;模型则用阿里巴巴的模型做测试 .env 文件为&#xff1a; OPENAI_API_KEYsk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx OPENAI_API_BASEhttps://dashscope.aliyuncs.com/compatible-mode…

【清晰教程】查看和修改Git配置情况

目录 查看安装版本 查看特定配置 查看全局配置 查看本地仓库配置 设置或修改配置 查看安装版本 打开命令行工具&#xff0c;通过version命令检查Git版本号。 git --version 如果显示出 Git 的版本号&#xff0c;说明 Git 已经成功安装。 查看特定配置 如果想要查看特定…

JAVA 常用 API 正则表达式

1 正则表达式作用 作用一&#xff1a;校验字符串是否满足规则作用二&#xff1a;在一段文本中查找满足要求的内容 2 正则表达式规则 2.1 字符类 package com.bjpowernode.test14;public class RegexDemo1 {public static void main(String[] args) {//public boolean matche…

光电设计大赛智能车激光对抗方案分享:低成本高效备赛攻略

一、赛题核心难点与备赛痛点解析 全国大学生光电设计竞赛的 “智能车激光对抗” 赛题&#xff0c;要求参赛队伍设计具备激光对抗功能的智能小车&#xff0c;需实现光电避障、目标识别、轨迹规划及激光精准打击等核心功能。从历年参赛情况看&#xff0c;选手普遍面临三大挑战&a…

Python实现P-PSO优化算法优化BP神经网络回归模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在当今数据驱动的时代&#xff0c;回归分析作为预测和建模的重要工具&#xff0c;在科学研究和工业应用中占据着重要…

Microsoft的在word中选择文档中的所有表格进行字体和格式的调整时的解决方案

找到宏 创建 并粘贴 使用 Sub 全选所有表格() Dim t As Table an MsgBox("即将选择选区内所有表格&#xff0c;若无选区&#xff0c;则选择全文表格。", vbYesNo, "reboot提醒您!") If an - 6 Then Exit Sub Set rg IIf(Selection.Type wdSelectionIP, …

C++23:关键特性与最新进展深度解析

文章目录 范围的新功能与增强元组的优化与新特性字符与字符串的转义表示优化std::thread::id的改进与扩展栈踪迹的格式化支持结论 C23作为C标准的最新版本&#xff0c;带来了许多令人瞩目的改进和新特性。从新的范围和元组功能到对字符和字符串转义表示的优化&#xff0c;再到 …

鲲鹏Arm+麒麟V10 K8s 离线部署教程

针对鲲鹏 CPU 麒麟 V10 的离线环境&#xff0c;手把手教你从环境准备到应用上线&#xff0c;所有依赖包提前打包好&#xff0c;步骤写成傻瓜式操作指南。 一、环境规划# 准备至少两台机器。 架构OS作用Arm64任意&#xff0c;Mac 也可以下载离线包Arm64麒麟 V10单机部署 K8s…

PGSQL结合linux cron定期执行vacuum_full_analyze命令

‌VACUUM FULL ANALYZE 详解‌ 一、核心功能 ‌空间回收与重组‌ 完全重写表数据文件&#xff0c;将碎片化的存储空间合并并返还操作系统&#xff08;普通 VACUUM 仅标记空间可重用&#xff09;。彻底清理死元组&#xff08;已删除或更新的旧数据行&#xff09;&#xff0c;解…

C#定时器深度对比:System.Timers.Timer vs System.Threading.Timer性能实测与选型指南

本文通过真实基准测试揭秘两种常用定时器的性能差异&#xff0c;助你做出最佳选择 一、C#定时器全景概览 在C#生态中&#xff0c;不同定时器适用于不同场景。以下是主流定时器的核心特性对比&#xff1a; 定时器类型命名空间适用场景触发线程精度内存开销依赖框架System.Wind…

解决8080端口被占问题

文章目录 1. 提出问题2. 解决问题2.1 查看占用8080端口的进程2.2 杀死占用8080端口的进程2.3 测试问题是否已解决3. 实战小结1. 提出问题 运行Spring Boot项目,报错8080端口被占 2. 解决问题 2.1 查看占用8080端口的进程 执行命令:netstat -ano | findstr :8080 2.2 杀死占用…

介绍一种LDPC码译码器

介绍比特翻转译码原理以及LDPC码译码器的设计。 1 译码理论 比特翻转&#xff08;BF&#xff09;译码算法是硬判决算法的一种。 主要译码思想是&#xff1a;当有一个校验矩阵出错时&#xff0c;BF 算法认为在这个校验矩阵中一定至少存在一个位置的码字信息是错误的&#xff1…

3DMAX+Photoshop教程:将树木和人物添加到户外建筑场景中的方法

在本教程中&#xff0c;我将向您展示如何制作室外场景。我不会详细解释每一个细节&#xff0c;而是想快速概述一下我的方法。 在本教程中&#xff0c;我使用了一个相对简单的3D模型&#xff0c;并向您展示了在一些高质量纹理的帮助下可以做什么。此外&#xff0c;我将向您展示…

随记 配置服务器的ssl整个过程

第一步 先了解到这个公钥私钥服务器自己可以生成&#xff0c;但是没什么用&#xff0c;浏览器不会信任的&#xff0c;其他人访问不了。所以要一些中间机构颁布的证书才有用。 一般的服务器直接 安装 Certbot 和插件 //CentOS Nginx 用户&#xff1a; sudo yum install epe…

数据库高可用架构设计:集群、负载均衡与故障转移实践

关键词:数据库高可用,HA架构,数据库集群,负载均衡,故障转移,SQL Server Always On,MySQL InnoDB Cluster,高可用性组,读写分离,灾难恢复 在当今瞬息万变的数字化时代,数据的价值日益凸显,数据库作为承载核心业务数据的基石,其可用性直接决定了业务的连续性与用户…

从0到1:多医院陪诊小程序开发笔记(上)

概要设计 医院陪诊预约小程序&#xff1a;随着移动互联网的普及&#xff0c;越来越多的医院陪诊服务开始向线上转型, 传统的预约方式往往效率低下&#xff0c;用户需耗费大量时间进行电话预约或现场排队&#xff0c;陪诊服务预约小程序集多种服务于一体&#xff0c;可以提高服…

建立连接后 TCP 请求卡住

大家读完觉得有意义记得关注和点赞&#xff01;&#xff01;&#xff01; 这篇文章描述了一个内核和BPF网络问题 以及故障排除步骤&#xff0c;这是一个值得深入研究的有趣案例 Linux 内核网络复杂性。 目录 1 故障报告 1.1 现象&#xff1a;概率健康检查失败 1.2 范围&am…

hive 笔记

1. 查看hive表的文件情况 搭建ui界面机器上查看 show create table xxx;得到文件地址 hdfs查看文件情况 hdfs dfs -ls hdfs://HDFS4005133/usr/hive/warehouse/xxx/xxxx/app_idxxx

无线通信模块简介

QuecPython 是运行在无线通信模块上的开发框架。对于首次接触物联网开发的用户而言&#xff0c;无线通信模块可能是一个相对陌生的概念。本文主要针对无线通信和蜂窝网络本身&#xff0c;以及模块的概念、特性和开发方式进行简要的介绍。 无线通信和蜂窝网络 物联网对无线通信…

把 CURSOR 的工具活动栏改成和 VSCODE 一样的左侧展示

目前使用cursor的时候发现工具栏与vscode的布局不一致&#xff0c;cursor在顶部导致操作起来不方便&#xff0c;如何改成与vscode相同的左侧布局展示。 解决方案 文件→首选项→设置&#xff0c;进入设置中&#xff0c;然后点击这个icon图标&#xff0c;可以打开配置文件 se…