双向链表详解

news2025/3/1 8:19:02

目录

一,双向链表的概念及结构 

二,双向链表的方法及其实现

2.1 双向链表

2.2 addFirst(int data) - 头插法 

2.3 addLast(int data) - 尾插法

2.4 size() - 链表长度

2.5 display() - 打印链表内容

2.6 clear() - 删除链表

2.7 addIndex(int index, int data) - 任意位置插入

2.8 contains(int key) - 链表当中是否有key

2.9 remove(int key) - 删除链表中第一次出现的key

2.10 removeAllKey(int key) - 删除所有值为key的节点


一,双向链表的概念及结构 

与单向链表相同,只不过每一个节点中多了一个空间来存储上一个节点的地址,结构如下图所示:

二,双向链表的方法及其实现

2.1 双向链表

链表类的定义及我们接下来要实现的方法,如下代码:

public class LinkedList {
    static class ListNode{//节点类 - 因为节点是链表的属性,所以用static来修饰
        //节点的成员
        public int val;
        public ListNode prev;
        public ListNode next;
        public ListNode(int val){
            this.val = val;
        }
    }
    public ListNode head;//头节点 - 不是每个节点都是头节点,它是链表的属性,所以定义在节点类外面
    public ListNode last;//尾节点 - 同头节点

    //头插法
    public void addFirst(int data){}

    //尾插法
    public void addLast(int data){}

    //在任意位置插入,假设第一个节点的下标为0
    public void addIndex(int index, int data){}

    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){}

    //删除第一次出现关键字为key的节点
    public void remove(int key){}

    //删除所有值为key的节点
    public void removeAllKey(int key){}

    //得到单链表的长度
    public int size(){}

    //打印链表内容
    public void display(){}

    //删除链表
    public void clear(){}
}

2.2 addFirst(int data) - 头插法 

顾名思义,就是在头节点之前插入一个节点,并将其变成头节点。 如图

但是我们还要注意如果链表当中没有元素的情况,如图:

    public void addFirst(int data){
        ListNode node = new ListNode(data);//创建一个节点
        if(head == null){//无元素的情况
            head = node;
            last = node;
            return;
        }
        head.prev = node;//1
        node.next = head;//2
        head = node;//4
    }

2.3 addLast(int data) - 尾插法

 但是我们还要注意如果链表当中没有元素的情况,如图:

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

2.4 size() - 链表长度

遍历链表

    public int size(){
        ListNode cur = head;//不能直接用head遍历,会改变head节点
        int count = 0;
        while(cur != null){
            cur = cur.next;
            count++;
        }
        return count;
    }

2.5 display() - 打印链表内容

遍历链表

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

2.6 clear() - 删除链表

遍历链表 - 将所有值置为空

    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.7 addIndex(int index, int data) - 任意位置插入

1.  要先判断他输入的下标合不合法

2.  看下标是不是头节点,尾节点,是的话直接调用头插法,尾插法

3.  如图

   public void addIndex(int index,int data){
        if(index < 0 || index > size()) {
            System.out.println("index不合法!");
            return;
        }
        if(index == 0) {
            addFirst(data);
            return;
        }
        if(index == size()) {
            addLast(data);
            return;
        }
        //cur拿到了index下标的节点的地址
        ListNode cur = head;
        while (index != 0) {
            cur = cur.next;
            index--;
        }
        ListNode node = new ListNode(data);
        node.prev = cur.prev;
        node.next = cur;
        cur.prev.next = node;
        cur.prev = node;
    }

2.8 contains(int key) - 链表当中是否有key

遍历链表

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

2.9 remove(int key) - 删除链表中第一次出现的key

1. 先找到key所在的位置

2. 判断是不是头节点,如果是且不只有一个元素 

如果是头节点且只有一个头节点:

3. 再判断是不是尾节点,如果是:

4.是中间节点,如图:

 

    public void remove(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                    if(head == null){//只有一个元素
                        last = null;
                    }else {//有多个元素
                        head.prev = null;
                    }
                }else {
                    if(cur == last){//尾节点
                        last = last.prev;
                        last.next = null;
                    }else {//中间节点
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

2.10 removeAllKey(int key) - 删除所有值为key的节点

与remove方法相同,只不过删除成功后不要return,继续往后遍历:

    public void removeAllKey(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                    if(head == null){
                        last = null;
                    }else {
                        head.prev = null;
                    }
                }else {
                    if(cur == last){//尾节点
                        last = last.prev;
                        last.next = null;
                    }else {
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
                //return这里不同
            }
            cur = cur.next;
        }
    }

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

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

相关文章

TOOM舆情监控与舆情传播:塑造有益信息环境

随着互联网和社交媒体的快速发展&#xff0c;舆情传播成为了影响社会舆论和公众意见的重要因素。然而&#xff0c;不可避免地&#xff0c;虚假信息、谣言和负面舆情也随之而来&#xff0c;对公众和社会造成了负面影响。在这样的背景下&#xff0c;舆情监控作为一种强有力的工具…

一出社会就在外包划水5年,已经废了

要不是女朋友和我提分手&#xff0c;我估计现在还没醒悟 本科大专&#xff0c;17年通过校招进入某软件公司做测试&#xff0c;干了接近5年的功能。 今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经在…

uboot的使用

目录 串口调试 1.uboot模式 自启动模式&#xff1a; 交互模式 2.uboot帮助命令 3.uboot环境变量 4.uboot常用环境变量 5.uboot网络传输命令 6.uboot存储器访问命令 7.uboot自启动环境变量 串口调试 1.串口连接开发板&#xff0c;通过 "设备管理器" 获取对…

JavaWeb概述

WEB服务器软件: 从Browser端发送数据到server端&#xff0c;我们称为请求&#xff0c;request 从Server端向浏览器端发送数据&#xff0c;我们称为相应&#xff0c;英语单词&#xff0c;response 关于Tomcat服务器的目录: bin:这个目录是Tomcat服务器的命令文件存放的目录&…

[SpringBoot]MyBatis Plus框架使用selectCount

目录 MyBatis Plus介绍 CRUD操作使用 添加依赖: 接口应该继承自BaseMapper 在继承自BaseMapper的泛型实体类上使用TableName注解指定数据表的名称 在类中与主键对应的属性上使用TableId注解指定主键的值如何处理 另外&#xff0c;原本应该做的配置不变&#xff0c;例如在…

OPC UA 云端模型库

UA 云库&#xff08;opc ua cloud library&#xff09;是互联网上可用的中央库&#xff0c;可以在其中上传配套规范 &#xff08;CS&#xff09; 并将其提供给其他人。许多CS是由OPC基金会的联合工作组开发和发布的。来自不同行业和应用领域的几位专家共同努力&#xff0c;为许…

水库大坝安全监测具体内容

水库大坝实时监测的主要任务是实时监测各个监测点水库水位、水压、渗流、流量、扬压力等&#xff0c;用无线传感网络完成数据传输&#xff0c;在计算机上用数据模式或图形模式反映出来&#xff0c;实时掌控整个水库大坝各项变化情况&#xff0c;特殊数据实行声光报警。大坝安全…

面试官:深拷贝与浅拷贝有啥区别?

文章目录 1.前言2.基本类型的拷贝3.引用类型的拷贝3.1 关于引用类型的浅拷贝3.2 关于引用类型的深拷贝 1.前言 首先&#xff0c;明确一点深拷贝和浅拷贝是针对对象属性为对象的&#xff0c;因为基本数据类型在进行赋值操作时&#xff08;也就是拷贝&#xff09;是直接将值赋给…

官宣!Databend 和 XSKY星辰天合达成合作

近日&#xff0c;北京数变科技有限公司与北京星辰天合科技股份有限公司完成了产品兼容性适配互认证。 本次测试是对 Databend 云原生数据仓库平台与星辰天合企业级存储产品&超融合产品进行严格的联合测试验证&#xff0c;结果显示&#xff0c;双方产品完全兼容&#xff0c;…

日撸java三百行day58

文章目录 说明Day58 符号型数据的 NB 算法1.基础理论知识1.1 条件概率1.2 独立性假设1.3 Laplacian 平滑 2. 符号型数据的预测算法跟踪2.1 testNominal()方法2.1.1 NaiveBayes 构造函数2.1.2 calculateClassDistribution()2.1.3 calculateConditionalProbabilities()方法2.1.4 …

STM32F4_SPI协议详解

目录 1. 什么是SPI 2. SPI物理层 3. SPI协议层 3.1 SPI基本通讯过程 3.2 数据有效性 3.3 CPOL/CPHA及通讯模式 4. SPI框图及通讯过程 4.1 SPI框图 4.2 通讯过程 5. SPI初始化结构体 6. Flash芯片(W25Q128)简介 7. 库函数配置SPI1的主模式 8. 实验程序 8.1 实验程…

“金九银十”是找工作的最佳时期吗?那倒未必

金九银十找工作 优势&#xff1a; 供选择的公司多&#xff0c;机会多 劣势&#xff1a; 人才供应量旺盛 成为备胎的几率大增&#xff0c;获取offer的时间较慢 若无明显竞争力&#xff0c;薪资涨幅相对不会太高 比起那些在跳槽季(金三银四&#xff0c;金九银十)扎堆找工作…

【LED子系统深度剖析】九、数据结构详解(番外篇)

个人主页:董哥聊技术 我是董哥,高级嵌入式软件开发工程师,从事嵌入式Linux驱动开发和系统开发,曾就职于世界500强公司! 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 文章目录 1、核心数据结构1.1 gpio_led_platform_data1.2 gpio_leds_priv1.3 gpio_led1.4 gpi…

2022年营收31.88亿,国产模拟 IC 头部企业持续扩充品类促发展

国产IC增速快于全球 IC &#xff0c; 国产替代空间广阔 根据 WSTS 的数据&#xff0c;2021 年全球 IC 市场规模高增 28.2%&#xff0c;2022 年全球 IC 市场规模同比增速放缓至 3.7%&#xff0c;由于需求减弱&#xff0c;且全球各下游仍在消化库存&#xff0c;预计 2023 年全球…

浮点数在内存中的存储以及用指针改变内存与强制转换的区别

文章目录 浮点型在内存中的存储引例浮点数的表示形式浮点数的存储E不全为零且E不全为1E全为0E全为1 Eg 总结用指针改变内存和强制转换的区别 浮点型在内存中的存储 引例 我们先来看下面一段代码 #include<stdio.h>int main() {int n 9;float* pFloat (float*)&n;p…

【来不及刷题之】33、合并区间(+ 删除被覆盖区间)

1. 删除被覆盖区间 先来看与合并区间比较相似的一道题目&#xff1a;删除被覆盖的区间 思路&#xff1a; 起点按照升序排序&#xff0c;终点按照降序排序基于以上排序规则&#xff0c;相邻的两个区间会有以下三种情况&#xff1a; 第一种情况&#xff1a;找到一个覆盖区间&a…

axios封装时对config参数的一点思考

目 录 0、起因1、冷静分析2、一个简单粗糙但是能用的封装 0、起因 创建一个实例&#xff1a; const service axios.create({baseURL: "/api",timeout: 3e3,withCredentials: true,headers:{"Content-Type": "application/json"} })简单封装&a…

STM32控制OLED介绍

OLED&#xff0c;即有机发光二极管&#xff08;Organic Light-Emitting Diode&#xff09;&#xff0c;又称为有机电激光显示&#xff08;Organic Electroluminesence Display&#xff0c; OELD&#xff09;。 OLED 由于同时具备自发光&#xff0c;不需背光源、对比度高、 厚度…

人工智能(pytorch)搭建模型7-利用pytorch搭建一个BiLSTM+CRF模型,实现简单的命名实体识别

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型7-利用pytorch搭建一个BiLSTMCRF模型&#xff0c;实现简单的命名实体识别&#xff0c;BiLSTMCRF 模型是一种常用的序列标注算法&#xff0c;可用于词性标注、分词、命名实体识别等任务。本…

软件安全概述

软件定义是&#xff1a;计算机程序、规则和可能相关的文档。 软件是程序、数据和文档的集合体。 零日漏洞、零日攻击 零日漏洞是指未被公开披露的软件漏洞&#xff0c;没有给软件的作者或厂商以时间去为漏洞打补丁或是给出建议解决方案&#xff0c;从而攻击者能够利用这种漏洞破…