LinkedList概念+MyLinkedList的实现

news2024/11/17 23:56:11

文章目录

  • LinkedList笔记
    • 一、 LinkedList
      • 1.概念
      • 2.LinkedList的构造方法
      • 3.LinkedList的遍历
    • 二、MyLinkedList的实现
      • 1.定义内部类
      • 2.打印链表、求链表长度、判断是否包含关键字
      • 3. 头插法和尾插法
      • 4.在任意位置插入
      • 5.删除结点
      • 6.清空链表


LinkedList笔记


一、 LinkedList

1.概念

LinkedList的底层是一个双向链表
在这里插入图片描述

  • 在插入和删除时,不用挪动元素
  • 在获取尾部结点时,不需要遍历获取,直接利用last结点

2.LinkedList的构造方法

  • 分为无参构造和有参构造
    在这里插入图片描述

有参:使用其他集合容器中元素构造List
在构造LinkedList的时候,传递的参数的类型要满足指定泛型的上界,同时要实现Collection接口

3.LinkedList的遍历

分别用重写的print方法、foreach、迭代器进行遍历

 public static void main(String[] args) {
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("hello");
        linkedList.add("world");
        linkedList.add("!");
        linkedList.add("?");
        linkedList.add("|");
        System.out.println(linkedList);
        System.out.println("-----------");
        for (String x:linkedList) {
            System.out.print(x+" ");
        }
        System.out.println();
        System.out.println("-----------");
        //使用迭代器遍历-正向遍历
        ListIterator<String> it = linkedList.listIterator();
        while (it.hasNext()){
            System.out.print(it.next()+" ");
        }
        System.out.println();
        System.out.println("===========");

        ListIterator<String> rit = linkedList.listIterator(linkedList.size());
        while (rit.hasPrevious()){
            System.out.print(rit.previous()+" ");
        }

        //使用迭代器遍历-反向遍历
    }

二、MyLinkedList的实现

1.定义内部类

与单链表不同的是,双链表的结点新增了prev域

public class MyLinkedList {
    static class ListNode{
        public int val;
        public ListNode prev;//前驱
        public ListNode next;//后继

        public ListNode(int val) {//构造方法
            this.val = val;
        }
    }
    public ListNode head;//定义头结点
    public ListNode last;//定义尾结点

1.在内部类中定义结点的元素
2.定义构造器
3.创建头/尾结点

2.打印链表、求链表长度、判断是否包含关键字

与单链表的形式相同

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

    /**
     *求链表长度
     * @return int
     */
    public int size(){
        ListNode cur = head;
        int count = 0;
        while (cur!=null){
            count++;
            cur = cur.next;
        }
        return count;
    }

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

3. 头插法和尾插法

在这里插入图片描述

    /**
     * 头插法
     * o(1)
     * @param data
     */
    public void addFirst(int data){
        ListNode node = new ListNode(data);
        if (head ==null){
            head = node;
            last = node;
        }else {
            node.next = head;
            head.prev = node;
            head = node;//头结点前移
        }
    }

    /**
     * 尾插法o(1)
     */
    public void addLast(int data){
        ListNode node = new ListNode(data);
        if(head==null){
          head = node;
          last = node;
        }else{
            last.next = node;
            node.prev = last;
            last = node;
        }
    }  

因为尾插的时候有last结点,不用进行尾结点的遍历查找
所以双链表尾插的时间复杂度是 o(1)

4.在任意位置插入

在这里插入图片描述

  public void addIndex(int index, int data) {

        if (index < 0 || index > size()) {//判断索引是否超出
           return;
        }
        if (index == 0) {//利用头插
            addFirst(data);
            return;
        }
        if (index == size()) {//利用尾插
            addLast(data);
            return;
        }
        ListNode node = new ListNode(data);
        ListNode cur = head;
        while (index!=0){//找到索引的位置
            cur = cur.next;
            index--;
        }
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;
    }

1.先判断索引下标是否溢出
2.如果索引是开头或者末尾的位置,调用写好的头插法和尾插法
3.通过遍历找到索引的位置cur
4.将cur插入链表中

  • 先改变node的next域,
  • 将node与cur相连 将cur的前驱的next域,改为node,
  • 将node与cur的前一个结点相连
  • 将node前驱改为cur前驱的地址 将cur的前驱改为node的地址值

5.删除结点

在这里插入图片描述

    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;//head的前驱置为空
                    }

                } else {//删除中间或者尾部
                    cur.prev.next = cur.next;
                    if (cur == last) {//如果是尾部
                        last = last.prev;
                    } else {//删除的是中间
                        cur.next.prev = cur.prev;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

1.通过遍历找到值等于key的结点
2.如果要删的是头结点,头结点向后移动一位。如果移动后的头结点不为空,将此时头结点的前驱置为空
3.如果要删除的cur是尾结点,将cur前驱的地址值指向cur的下一个地址,将last向前移动一位
4.如果要删除的是中间结点,将cur前驱的地址值指向cur的下一个地址,将cur后继的前驱指向cur的前驱

6.清空链表

在这里插入图片描述

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

1.遍历链表,用curNext记录cur的下一个结点
2.将cur的前驱和后继置为null
3.将头结点和尾结点置为空。

点击移步博客主页,欢迎光临~

偷cyk的图

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

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

相关文章

IAR For ARM 安装教程

电脑环境 安装包下载 1、官网下载 ①搜索 IAR ②切换产品&#xff0c;选择Arm ③选择IAR Embedded Workbench for Arm ④免费试用 2、网盘下载 EWARM-CD-8202-14838.exe(访问密码: 1666) https://url48.ctfile.com/f/33868548-961057458-611638?p1666 软件下载 1、点击安…

华为数通方向HCIP-DataCom H12-831题库(多选题:41-60)

第41题 下列哪些属于VLAN聚合的优点? A、增加了编址的灵活性 B、增加了可用的VLAN数量 C、减少了IP地址的浪费 D、实现Sub-VLAN间广播域的隔离 答案:ACD 解析: 各个Sub-VLAN作为一个独立广播域实现广播隔离,又节省了IP地址资源,提高了编址的灵活性 第42题 在进行结构化的…

【Java 进阶篇】Java Tomcat 入门指南

Java Tomcat&#xff08;通常简称 Tomcat&#xff09;是一个流行的开源Servlet容器&#xff0c;用于托管Java Web应用程序。它是Apache软件基金会的一部分&#xff0c;提供了一个稳定、可靠的环境来运行Java Servlets和JavaServer Pages&#xff08;JSP&#xff09;。本篇博客将…

mariadbmysql更改数据库默认存储路径

1.登录数据库查询默认存储位置 默认存储在/var/lib/mysql show variables like "%datadir%"; 2.先停止服务 systemctl stop mariadb 3.移动数据文件 mv /var/lib/mysql/ /home/ 4.修改服务配置 vim /etc/my.cnf.d/server.cnf5.在 [mysqld] 下面增加 datadir/ho…

4.2 QPainter的绘图接口介绍(下)

4.2 QPainter的绘图接口介绍(下) 上篇文章中我们举例介绍了drawRect、drawRoundRect、drawEllipse、drawArc、drawChord、drawPie这几个接口的用法,本篇文章继续讲解绘图的接口。 QPainter::drawText(绘制文字) 关于drawText的重载方法,我们可以将其分为两类来进行说明。…

基于Qt 的CAN Bus实现

# 简介 从 Qt5.8 开始,提供了 CAN Bus 类,假设您的 Qt 版本没有 CAN Bus,可以参考 Linux 应用编程来操控开发板的 CAN,目前我们主要讲解 Qt 相关的 CAN编程。其实 Qt 也提供了相关的 Qt CAN 的例子,我们也可以直接参考来编程。读者手上需要有测试 CAN 的仪器!否则写好程…

手机游戏定制研发手机软件开发

手机游戏定制研发是一个多阶段的过程&#xff0c;它使开发者能够根据客户的需求和创意&#xff0c;构建独特的游戏体验。这个领域是一个蓬勃发展的市场&#xff0c;因为手机游戏在全球范围内都备受欢迎。在本文中&#xff0c;我们将深入探讨手机游戏定制研发的主要步骤以及关键…

目标检测应用场景—数据集【NO.15】叶片虫害检测

写在前面&#xff1a;数据集对应应用场景&#xff0c;不同的应用场景有不同的检测难点以及对应改进方法&#xff0c;本系列整理汇总领域内的数据集&#xff0c;方便大家下载数据集&#xff0c;若无法下载可关注后私信领取。关注免费领取整理好的数据集资料&#xff01;今天分享…

python连接sqlserver

安装 pip install pyodbc 导入 import pyodbc 建立连接 con pyodbc.connect(DRIVER{SQL Server};SERVER192.168.202.173;DATABASEAIS20230802091529;UIDsa;PWDchief.cc1993) 游标 cursorcon.cursor() 查询 sql"select * from T_SAL_OUTSTOCK where FBillNoXSCKD…

GDB常用指令与调试汇总

文章目录 前言一、基础二、例子三、用gdb调试多线程程序 前言 GDB&#xff08;GNU Debugger&#xff09;是一个强大的调试工具&#xff0c;用于调试C、C等编程语言的程序。本文将介绍一些常用的GDB指令&#xff0c;以及通过例子演示如何使用这些指令进行程序调试。 一、基础 …

java--if语句

1.if语句 根据条件(真或假)来决定执行某段代码。 2.if语句有三种形式 执行流程&#xff1a; 首先判断条件表达式的结果&#xff0c;如果为true执行语句体&#xff0c;为false就不执行语句体。 注意事项&#xff1a; if语句中&#xff0c;如果大括号控制的只有一行代码&am…

【从0到1设计一个网关】网络通信框架Netty的设计

文章目录 Netty架构实现NettyHttpServer实现NettyHttpServerHandler实现NettyProcessor实现NettyHttpClient实现核心容器效果演示注:本文所有代码均已开源在Github上。 源码地址: 项目源码 完成当前章节后,代码效果演示如下: 这个请求将会重定向转发到我们后端的localhost…

woyaojiangzhang

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 博主接触FineReport帆软报表有一段时间了&#xff0c;正好前几天做了一个任务日历的需求&#xff0c;把每天完成的任务量直观的展示在日历上&#xff0c;方便管理者更好的监控各业务的完成情况&#xff0c;做完后想着…

S32K324 UDS Bootloader开发-需求篇

文章目录 前言内存分配UDS诊断协议需求CAN ID及时间参数UDS诊断服务Bootloader诊断服务APP诊断服务 DID22服务的DID:2E服务的DID:Routine Control DID&#xff1a; 刷写流程预编程主编程后编程 总结 前言 之前做过一个STM32的UDS Bootloader&#xff0c;协议栈主要是NXP官网下…

坦克世界WOT知识图谱之知识图谱篇

文章目录 关于Neo4j1. neo4j安装及配置&#xff1a;2. 确定三元组3. 代码实现结束语 关于Neo4j Neo4j是一个高性能的&#xff0c;NOSQL图形数据库。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎&#xff0c;但是它将结构化数据存储在网络(从数学角度叫做…

UG\NX二次开发 设置视图中心 UF_VIEW_set_center

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 感谢粉丝订阅 感谢 a1794902437 订阅本专栏,非常感谢。 简介 UG\NX二次开发 设置视图中心 UF_VIEW_set_center。如果视图NULL_TAG,则使用工作视图。 效果 代码 #include &qu…

【PointNet—论文笔记分享】

第一个直接基于原始点云数据进行分割、分类的模型&#xff0c;之前都是基于多视图或者体素的方式。 论文: PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation代码: TensorFlow版 Pytorch版 基本模型架构&#xff1a; 分别对每个点进行特征提取…

AI大模型基础环境搭建

文章目录 AI大模型基础环境搭建简介下面是搭建大模型基础环境大模型基础环境通常会依赖以下package&#xff1a;conda安装demo环境搭建关于该git项目需要注意的一些点前后端封装 AI大模型基础环境搭建 简介 简单描述一下本文章里会教大家做的东西 1、搭建大模型基础环境 2、f…

JVM相关的面试题

一、什么是程序计数器 二、简要的介绍一下堆 三、什么是虚拟机栈 四、能不能解释下方法区 五、你听过直接内存吗&#xff1f; 六、什么是类加载器&#xff0c;类加载器有哪些 七、什么是双亲委派模型 八、JVM为什么采用双亲委派机制 九、类装载的执行过程 十、对象什么时候被垃…

Day982.各大开放平台是如何使用OAuth 2.0 -OAuth 2.0

各大开放平台是如何使用OAuth 2.0 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于各大开放平台是如何使用OAuth 2.0的内容。 “开放平台”&#xff0c;不难理解&#xff0c;它的作用就是企业把自己的业务能力主要以开放 API 的形式&#xff0c;赋能给外部开发者。而…