【java-数据结构14-双向链表的增删查改2】

news2024/11/24 8:30:27

   上一篇文章中,我们已经对双向链表进行一些基本操作,本篇文章我们继续通过对链表的增删查改来加深对链表的理解~同时有任何不懂的地方可以在评论区留言讨论,也可以私信小编~觉得小编写的还可以的可以留个关注支持一下~话不多说正片开始~

注意:上篇文章少了一些图,这里做些补充重新发一遍

1.任意位置插入

1.对插入位置进行合法性判断

2.如果等于0即为头插法,等于size即为尾插法

小于0大于saize都是不可以的,代码如下

private void checkIndex(int index) {
        if(index < 0 || index > size()) {
            throw new IndexOutOfException("index 不合法!"+index);
        }
    }

上面我们抛出一个自定义异常 ,也不要忘记定义一个异常类,代码如下

 public class IndexOutOfException extends RuntimeException{
        public IndexOutOfException() {
        }

        public IndexOutOfException(String message) {
            super(message);
        }
    }

3.定义cur,也就是要插入的位置

代码如下

public void addIndex(int index,int data){
        checkIndex(index);
        if(index == 0) {
            addFirst(data);
            return;
        }
        if(index == size()) {
            addLast(data);
            return;
        }
        ListNode cur = searchIndex(index);
        ListNode node = new ListNode(data);
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;
    }

调用测试

public class test {
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.addFirst(56);
        myLinkedList.addFirst(45);
        myLinkedList.addFirst(34);
        myLinkedList.addFirst(23);
        myLinkedList.addFirst(12);
        myLinkedList.addLast(67);

        myLinkedList.display();
        myLinkedList.addIndex(0,999);
        myLinkedList.display();
     
    }

运行截图 

2.删除第一次出现的key节点

  如果是单链表,我们是需要找到要删除的前一个节点的,让删除的节点被跳过即可

  双链表则不需要那么麻烦,我们先看中间节点,直接找到要删除的节点cur,让cur.prev.next = cur.next; cur.next.prev = cur.prev;即可 如图

接下来我们讨论如果要删除的是头节点 :先让head = head.next并且head.prev = null

注意:那么如果只有一节点呢head = head.nex代码执行完毕后head就为null,那么head.prev = null就会异常,那么我们要加一个前置条件if:head!=null,如果head等于null,手动把last置为空即可

下面我们讨论要删除的是尾巴节点cur.prev.next = cur.next; last = last.prev

代码如下

 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 {
                        last = null;
                    }
                }else {
                    //删除中间节点 和  尾巴节点
                    if(cur.next != null) {
                        //删除中间节点
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }else {
                        //尾巴节点
                        cur.prev.next = cur.next;
                        last = last.prev;
                    }
                }
                return;
            }else {
                cur = cur.next;
            }
        }
    }

调用测试

 public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.addFirst(56);
        myLinkedList.addFirst(45);
        myLinkedList.addFirst(34);
        myLinkedList.addFirst(23);
        myLinkedList.addFirst(12);
        myLinkedList.addLast(67);

        myLinkedList.display();
       myLinkedList.remove(23);
       
        myLinkedList.display();
     


    }

运行截图

 

3.删除所有出现的key节点

    此题逻辑与上题基本相同,只是我们上一个题删除第一个节点后就返回了,我们只要让cur继续往后走即可

代码如下

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 {
                        last = null;
                    }
                }else {
                    //删除中间节点 和  尾巴节点
                    if(cur.next != null) {
                        //删除中间节点
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }else {
                        //尾巴节点
                        cur.prev.next = cur.next;
                        last = last.prev;
                    }
                }
                cur = cur.next;
                //return;
            }else {
                cur = cur.next;
            }
        }
    }

调用测试

 public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.addFirst(56);
        myLinkedList.addFirst(45);
        myLinkedList.addFirst(12);
        myLinkedList.addFirst(12);
        myLinkedList.addFirst(12);
        myLinkedList.addLast(67);

        myLinkedList.display();
        myLinkedList.removeAllKey(12);
     
        myLinkedList.display();
    


    }

运行截图 

4.清空链表

head,last置为null,或者一个一个置null,如图

 

但此时还有head,last两个节点,手动置空即可 

代码如下

 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;
    }

调用测试

 public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.addFirst(56);
        myLinkedList.addFirst(45);
        myLinkedList.addFirst(12);
        myLinkedList.addFirst(12);
        myLinkedList.addFirst(12);
        myLinkedList.addLast(67);

        myLinkedList.display();
        myLinkedList.clear();
     
        myLinkedList.display();
    

    }

运行截图

5.库中的linkedlist方法使用

 到此为止,我们手动创建链表并对链表进行增删查改就结束的,其实我们还可以通过 库当中的linkedlist,直接使用,下面我们做具体演示

1.导入类:import java.util.List

2.创建链表。

  List<Integer> list1 = new LinkedList<>();

下面是一些方法,这里不做演示了

 

6.LinkedList遍历 

1.for循环

这个方法前面有讲过,这里不多赘述

2.for,each循环

代码如下

 public static void main(String[] args) {
        List<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(1);
        list.add(3);
        for (Integer X:list
             ) {
            System.out.println(X);
        }

    }

运行截图

 

3.迭代器· 

使用迭代器要导入类:import java.util.ListIterator;

代码如下

 public static void main(String[] args) {
        List<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(1);
        list.add(3);
     
        ListIterator<Integer> it = list.listIterator();
        while(it.hasNext()){
            System.out.print(it.next()+ " ");
        }

    }

4.迭代器反向遍历

 

public static void main(String[] args) {
        List<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(1);
        list.add(3);
      
        ListIterator<Integer> rit = list.listIterator(list.size());
        while (rit.hasPrevious()){
            System.out.print(rit.previous() +" ");
        }
        System.out.println();
    }

 

到此为止,我们链表的章节就可以跟大家说在再见了,下一篇文章,我们将会进入栈和队列的学习,觉得小编讲的还可以的可以留个关注~我们下期再见~ 谢谢观看~

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

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

相关文章

「JavaEE」多线程案例分析3:线程池

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;JavaEE &#x1f387;欢迎点赞收藏加关注哦&#xff01; 线程池 &#x1f349;简介&#x1f349;标准库中的线程池&#x1f349;Executors&#x1f349;实现一个简单的线程池 &#x1f349;简介…

初始Django

初始Django 一、Django的历史 ​ Django 是从真实世界的应用中成长起来的&#xff0c;它是由堪萨斯&#xff08;Kansas&#xff09;州 Lawrence 城中的一个网络开发小组编写的。它诞生于 2003 年秋天&#xff0c;那时 Lawrence Journal-World 报纸的程序员 Adrian Holovaty 和…

识别AI论文生成内容,降低论文高AI率

AI写作工具能帮我们在短时间内高效生成一篇毕业论文、开通报告、文献综述、任务书、调研报告、期刊论文、课程论文等等&#xff0c;导致许多人开始使用AI写作工具作为撰写学术论文的辅助手段。而学术界为了杜绝此行为&#xff0c;开始使用AIGC检测系统来判断文章是由AI生成还是…

机器学习中的聚类

目录 认识聚类算法 聚类算法API的使用 聚类算法实现流程 聚类算法模型评估 认识聚类算法 聚类算法是一种无监督的机器学习算法。 它将一组数据分成若干个不同的群组&#xff0c;使得每个群组内部的数据点相似度高&#xff0c;而不同群组之间的数据点相似度低。常用的相似…

【3dmax笔记】028:倒角的使用方法

一、倒角描述 在3dmax中创建倒角效果可以通过多种方法实现,以下是几种常见的方法: 使用倒角修改器。首先创建一个图形(如矩形和圆),然后对齐它们,将它们转化为可编辑样条线,并附加在一起,选择要倒角的边缘,然后使用倒角修改器来调整高度、轮廓等参数。使用倒角剖面修…

Davinci工程vBaseEnv模块讲解

配合的模块 要正常使用vBaseEnv模块&#xff0c;要同时使能EcuC、OS、vBRS和vLinkGen模块。 OS是操作系统&#xff0c;除了FBL以外&#xff0c;其他都需要用到OS。 vBaseEnv是基础环境 vBRS是基本运行系统 vLinkGen脚本链接生成器 EcuC是ECU配置 EcuC配置 需要配合vBaseEnv模…

程序员的神奇应用:从代码创造到问题解决的魔法世界之持续集成/持续部署

文章目录 持续集成/持续部署 在软件开发的海洋中&#xff0c;程序员的实用神器如同航海中的指南针&#xff0c;帮助他们导航、加速开发、优化代码质量&#xff0c;并最终抵达成功的彼岸。这些工具覆盖了从代码编写、版本控制到测试和部署的各个环节。 在当今数字化的世界里&…

数字水印 | Arnold 变换的 Python 代码实现

&#x1f96d; 参考博客&#xff1a; Arnold 阿诺德置乱&#xff08;猫脸变换&#xff09;图像盲水印注入预处理&#xff08;Python&#xff09; 1 回顾&#xff1a;Arnold 公式 A r n o l d \mathsf{Arnold} Arnold 变换公式如下&#xff1a; [ x n 1 y n 1 ] [ 1 b a a b…

搜索引擎的设计与实现(二)

目录 3 搜索引擎的基本原理 3.1搜索引擎的基本组成及其功能 l.搜索器 (Crawler) 2.索引器(Indexer) 3.检索器(Searcher) 4.用户接口(UserInterface) 3.2搜索引擎的详细工作流程 4 系统分析与设计 4.1系统分析 4.2系统概要设计 4.2系统实现目标 前面内容请移步 搜索引…

力扣HOT100 - 70. 爬楼梯

解题思路&#xff1a; 动态规划 注意 if 判断和 for 循环 class Solution {public int climbStairs(int n) {if (n < 2) return n;int[] dp new int[n 1];dp[1] 1;dp[2] 2;for (int i 3; i < n; i) {dp[i] dp[i - 1] dp[i - 2];}return dp[n];} }

Co-Driver:基于 VLM 的自动驾驶助手,具有类人行为并能理解复杂的道路场景

24年5月来自俄罗斯莫斯科研究机构的论文“Co-driver: VLM-based Autonomous Driving Assistant with Human-like Behavior and Understanding for Complex Road Scenes”。 关于基于大语言模型的自动驾驶解决方案的最新研究&#xff0c;显示了规划和控制领域的前景。 然而&…

智能组网实施步骤?

随着信息技术的快速发展&#xff0c;智能组网正在逐渐成为各个行业的关注焦点。智能组网通过将各种设备、终端和系统连接起来&#xff0c;实现信息的传输和共享&#xff0c;从而提升工作效率和运营效益。本文将介绍智能组网的实施步骤&#xff0c;以及一家名为【天联】的智能组…

台式电脑屏幕亮度怎么调节?让你的眼睛更舒适!

在日常使用台式电脑时&#xff0c;调节屏幕亮度是一项常见的需求。不同的环境和个人偏好可能需要不同的亮度设置。因此&#xff0c;了解台式电脑屏幕亮度怎么调节是非常重要的。本文将介绍三种常见的方法&#xff0c;帮助您轻松调节台式电脑屏幕亮度&#xff0c;以满足您的需求…

【C++初阶】第十一站:list的介绍及使用

目录 list的介绍及使用 1.list的含义 2.list的介绍 3.list的使用 1.list的构造 2.list iterator的使用 3.list capacity 4.list element access 5 list modifiers 尾插尾删 和 头插头删 insert 和 erase resize swap clear 6.list sort and reverse 7.list copy vector copy li…

数字化转型:超越信息化,构建数字化营销体系!

在数字化的浪潮中&#xff0c;企业仅仅做好信息化数字能力基础已远远不够&#xff01;那么&#xff0c;还需要什么呢&#xff1f;没错&#xff0c;就是在数字化经营思维的指导下&#xff0c;建立起数字化营销体系和执行方案&#xff01;这是企业在数字时代中立于不败之地的关键…

在cmd中,如何使用cd进入指定文件目录

在cmd中&#xff0c;如何使用cd进入指定文件目录 1.要进入的磁盘与当前磁盘一致 例如: cd C:\Program Files (x86)\Google\Chrome\Application 2.进入到其他磁盘&#xff0c; 例如 cd /d D:\JAVA\codes\01\1.4 或者下面的方式&#xff08;直接输入磁盘F&#xff1a;和文件名…

11.php-fpm模板(监控页面取值)

php-fpm模板(监控页面取值) 开启监控页面配置 #修改php配置文件 vim /etc/php-fpm.d/www.conf pm.status_path /php_status#修改nginx配置文件,添加到nginx配置文件中 vim /etc/nginx/conf.d/default.conflocation /php_status {root html;fastcgi_pass 127.0.…

使用单片机的IO引脚直接驱动段码屏

使用单片机的IO引脚直接驱动段码屏,目的是为了降低成本。这种古老的应用,在低功耗产品中比较多见。 如:水表&#xff0c;燃气表等需要电池供电的产品。 下面纯属个人理解&#xff0c;未经测试。 1/3Duty表示LCD共有3个COM引脚,分别占显示周期的1/3 1/2BIAS表示电压0和VCC 1、…

想半天憋不出几个字?试试AI扩写

大家在写文章时是否也经常这样&#xff1f;想了半天&#xff0c;结果只能写出几个字&#xff0c;但是要求往往又是几百多个字&#xff0c;那么有没有啥工具可以帮我们在原文的基础上扩写一下文章字数&#xff0c;让我们达到字数要求呢&#xff1f; 下面给大家介绍一下如何扩写文…

Rpcx (二):传输

一、Transport 传输 rpcx 可以通过 TCP、HTTP、UnixDomain、QUIC和KCP通信。你也可以使用http客户端通过网关或者http调用来访问rpcx服务。 TCP 这是最常用的通信方式。高性能易上手。可以使用TLS加密TCP流量。 Example: 101basic 服务端使用 tcp 做为网络名并且在注册中心…