快速入门无头双链表

简介: 快速入门无头双链表

无头双向单链表的基础功能实现

在单链表的学习中,我们已经掌握了求单链表的长度,是否包含了某一个元素,以及打印单链表,无头双链表的求长度,判断是否包含了某一个元素,打印双链表,都是与单链表的写法一样的,所以这里就不在多做赘述。

头插法

变化前

变化后

代码实现:

 //头插法
        public void addFirst(int data){
        listnode add=new listnode(data);
        if (head==null){//还得考虑链表为空的情况
            head=add;
            last=add;
            return;
        }
        add.next=head;
        head.prve=add;
        head=add;
        }

尾插法

变化前

变化后

代码实现:

 //尾插法
        public void addLast(int data){
            listnode add=new listnode(data);
        if (head==null){//同样需要考虑要是有空列表的情况
            head=add;
            last=add;
            return;
        }
        last.next=add;
        add.prve=last;
        last=add;
        }

删除第一次出现关键字为key的节点

一般情况

出现在头部情况(假设要删除的第一次数据在头部出现):

出现在尾部(假设要删除的数据最后才第一次出现):

对以上情况进行分析之后,我们必须通过遍历来解决,具体实现代码如下:

//删除第一次出现关键字为key的节点
        public void remove(int key){
            if (head==null)return;
        listnode cur=head;
        while (cur!=null){
            if (cur.val==key){
                if (cur==head){
                    cur.next.prve=null;
                    head=head.next;
                }else{
                    cur.prve.next=cur.next;
                    if (cur==last){
                        last=cur.prve;
                    }else{
                        cur.next.prve=cur.prve;
                    }
                }
                return;
            }else{
                cur=cur.next;

            }
        }
        }

但是在这里代码是有缺陷的,因为如果就是一个节点的时候,那么此时代码会报错,我们就需要单独讨论一下,具体代码实现如下:

        public void remove(int key){
            if (head==null)return;
        listnode cur=head;
        while (cur!=null){
            if (cur.val==key){
                if (cur==head){
                    head=head.next;
                    if (head!=null){
                        head.prve=null;
                    }else{
                        last=null;//尾节点要变成null,不然会被一直引用
                    }
                }else{
                    cur.prve.next=cur.next;
                    if (cur==last){
                        last=cur.prve;
                    }else{
                        cur.next.prve=cur.prve;
                    }
                }

            }else{
                cur=cur.next;

            }
        }
        }

删除所有的值为key的节点

这个就需要在删第一次为key的基础上,把return去掉,然后要让cur一直往下走,具体实现代码如下:

//删除所有值为key的节点
        public void removeAllKey(int key){
            if (head==null)return;
            listnode cur=head;
            while (cur!=null){
                if (cur.val==key){
                    if (cur==head){
                        head=head.next;
                        if (head!=null){
                            head.prve=null;
                        }else{
                            last=null;
                        }

                    }else{
                        cur.prve.next=cur.next;
                        if (cur.next!=null){
                            cur.next.prve=cur.prve;
                        }else{
                           last=last.prve;
                        }
                    }
                }
                    cur=cur.next;
            }
        }

任意位置插入

插入前:

插入后

代码实现如下:

 //任意位置插入,第一个数据节点为0号下标
        public listnode search(int index){
            if (index<0||head==null)return null;
            listnode cur=head;
            while (index!=0){
                cur=cur.next;
                if (cur==null){//说明超出链表的长度
                    return null;
                }
                index--;
            }
            return cur;
        }
        public void addIndex(int index,int data){
            listnode listnode=new listnode(data);
            if (index==0){//如果是第一个位置就是头插法
                addFirst(data);
                return;
            }
            if (index==size()){//最后一个位置就是尾插法
                addLast(data);
                return;
            }
            listnode ret=search(index);
            if (ret==null)return;
            ret.prve.next=listnode;
            listnode.next=ret;
            listnode.prve=ret.prve;
            ret.prve=listnode;
        }

清空双链表

代码实现:

       public void clear(){
        while(head!=null){
            listnode cur=head.next;
            head.prve=null;
            head.next=null;
            head=cur;
        }
        last=null;//要把尾节点手动置为null,不然还在被引用
        }


双链表基本功能实现源码

单链表的功能实现

目录
相关文章
|
安全 小程序 物联网
WLAN基础 无线局域网配置方法 旁挂三层组网隧道转发方式配置
WLAN基础 无线局域网配置方法 旁挂三层组网隧道转发方式配置
1905 0
WLAN基础 无线局域网配置方法 旁挂三层组网隧道转发方式配置
|
10月前
|
人工智能 自然语言处理 搜索推荐
浙大通义联手推出慢思考长文本生成框架OmniThink,让AI写作突破知识边界
随着大模型(LLMs)的发展,AI 写作取得了较大进展。然而,现有的方法大多依赖检索知识增强生成(RAG)和角色扮演等技术,其在信息的深度挖掘方面仍存在不足,较难突破已有知识边界,导致生成的内容缺乏深度和原创性。
567 46
|
监控 数据可视化 项目管理
高效时间管理工具如何帮助优化日常任务管理?2024年6款最优秀软件
在快节奏的现代工作环境中,高效的时间管理和任务协作工具成为提升生产力的关键。2024年,随着工作模式的变化,企业及个人愈发依赖这些工具来优化时间管理、任务分配和团队协作。本文精选了几款高效工具,如板栗看板、ClickUp、Notion、Wrike、Todoist和Evernote,它们各自具备独特优势,适用于不同行业和规模的团队,帮助用户在繁忙的工作中保持高效和有序。
1873 6
高效时间管理工具如何帮助优化日常任务管理?2024年6款最优秀软件
视频格式转换与DRM解除
随着流媒体平台的普及,用户对视频下载和转换工具的需求不断增加。本文介绍了几款优秀工具,如CleverGet、PlayOn Cloud、CocCut、StreamGaGa和PlayOn Desktop,帮助用户更好地下载、转换和管理视频内容。这些工具不仅提升了视频获取的便利性,还提供了多种选择,满足不同需求。使用时请确保合法合规。
STM32速成笔记(六)—定时器
本文介绍了定时器的概念,作用。针对STM32F1的通用定时器做了详细介绍。此外,介绍了PWM的概念,用途以及STM32F1的PWM,给出了PWM频率的计算方法。最后通过介绍利用定时器的更新中断和PWM这两种方法实现呼吸灯,展示了定时器和PWM的配置步骤,并给出了详细的程序设计。另外,介绍了利用定时器实现按键长短按的检测方法。
685 0
STM32速成笔记(六)—定时器
|
存储 分布式计算 Hadoop
|
API Python
【Python】已解决:urllib.error.HTTPError: HTTP Error 403: Forbidden
【Python】已解决:urllib.error.HTTPError: HTTP Error 403: Forbidden
3853 2
|
安全 Java 网络安全
如何在Java中处理SSLHandshakeException异常?
如何在Java中处理SSLHandshakeException异常?
2356 1
|
前端开发 Java PHP
信息系统架构模型(1) MVC
信息系统架构模型(1) MVC
181 0
|
PHP
PHP字符串学习之怎么去除其他字符,只留下数字
在之前的文章《PHP字符串学习之将字符串分成更小长度的子串》中,我们介绍了分割字符串,将字符串分成更小子串的方法。这次继续PHP字符串的学习与练习,看看如何提取字符串中的数字字符,有需要的可以参考参考~ 本文的主题是:“提取字符串中的数字字符”。例如我们给出下面一个字符串 $str ='0我是123456一段测试的字789符串0'; 如何去除其他字符,只返回由字符串中数字字符组成的子串“01234567890”?下面给大家介绍两种方法:
346 0