数据结构--线性表双向链表的实现

目录

思路设计

总体思维导图

插入部分

头插法+尾插法

任意位置插入

删除部分

头结点

尾节点

中间节点

只有头结点且删除的就是头结点

​编辑

清空链表部分

遍历清空链表的所有节点

不遍历清空

各部分代码

Main部分

MyListedList部分

IndexOutOfException部分

总结


思路设计

设计Main,MyListedList,IndexOutOfException 三个文件。

Ma负责主函数的运行,MyList负责各种方法,IndexOut负责输入错误的提示。

总体思维导图

插入部分

头插法+尾插法

任意位置插入

删除部分

头结点

尾节点

中间节点

只有头结点且删除的就是头结点

清空链表部分

遍历清空链表的所有节点

不遍历清空

各部分代码

Main部分

public class Main {
    public static void main(String[] args) {
        //这个是顺序表的写法,现在是双向链表
        //MyListedList<Integer> myListedList= new MyListedList();

        MyListedList myListedList= new MyListedList();

        myListedList.addFirst(1);
        myListedList.addFirst(2);
        myListedList.addFirst(3);
        myListedList.addFirst(4);

        /*myListedList.addLast(1);
        myListedList.addLast(2);
        myListedList.addLast(3);
        myListedList.addLast(4);*/


        //System.out.println(myListedList.size());
        //System.out.println(myListedList.contains(10));
        //myListedList.display();

        //myListedList.addIndex(0,99);
        //myListedList.display();

        myListedList.removeAllKey(1);
        myListedList.clear();
        myListedList.display();

    }
}

MyListedList部分

public class MyListedList {

    static class ListNode{
        private int val;
        private ListNode prev;
        private ListNode next;

        //重写构造方法得以调用
        //才能保证下面传入的data能使用
        //ListNode node = new ListNode(data);
        public ListNode(int val) {
            this.val = val;
        }
    }

    //双向链表的头节点
    public ListNode head;
    //双向链表的尾节点
    public ListNode last;

    //得到单链表的长度
    //size,display,contains都是要遍历定义头指针
    public int size(){
        ListNode cur = head;
        int count = 0;
        while (cur != null){
            count++;
            cur = cur.next;
        }

        return count;
    }

    public void display(){
        //遍历定义一个头结点指针,让其不断往后走
        ListNode cur = head;
        while (cur != null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }

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


        //头插法
        public void addFirst(int data){
            ListNode node = new ListNode(data);

            //如果插入的节点的前后指针都是空的话
            //要修改链表里面的头尾指针
            if(head == null){
                head = node;
                last = node;
            }else {
                //先改变next再改变perv
                node.next = head;
                head.prev = node;
                head = node;
            }

        }
        //尾插法
        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 = last.next
            }
        }
        //任意位置插入,第一个数据节点为0号下标
        public void addIndex(int index,int data){
            checkIndex(index);

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

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

            //声明cur
            ListNode cur = seachIndex(index);
            ListNode node = new ListNode(data);
            node.next = cur;
            cur.prev.next = node;
            node.prev = cur.prev;
            cur.prev = node;

        }

        //定义cur找到插入的位置
        private ListNode seachIndex(int index){
            ListNode cur = head;

            while (index != 0){
                cur = cur.next;
                index--;
            }
            return cur;
        }

        private void checkIndex(int index){
            if (index < 0 || index > size()){
                //可以自定义抛出RuntimeException(运行异常)一个异常

                throw new IndexOutOfException("index 不合法!"+index);

            }
        }

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

            ListNode cur = head;
            if(head == null) {
                head = cur;
                last = cur;
            }

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

            }

        }
        //删除所有值为key的节点
        public void removeAllKey(int key){
            ListNode cur = head;
            if(head == null) {
                head = cur;
                last = cur;
            }

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

                    }
                    //删除key数据了之后往后走,查看
                    //是否还有要删除的数据去遍历
                    cur = cur.next;
                    //return;
                }else {
                    //就算这个数据不是我要删除的数据,我也往后走去遍历
                    cur = cur.next;
                }

            }
        }

        public void clear(){

            ListNode cur = head;

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

IndexOutOfException部分

public class IndexOutOfException extends RuntimeException{

    //提供两个构造方法
    public IndexOutOfException() {
    }

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

总结

部分方法大体上写法都大致相同,关键在于具体方法部分,比如:删除的节点就只有一个,而且这个要删除的节点就是头结点,那么这种特殊情况是在写完正常删除操作后,输入数据判断得到的结果,针对这样的情况要画图分析,一步一步慢慢思考如何设计程序代码,出错没有关系,再次调试画图看看有没有漏掉的地方,一次次修改相信最终会获得成功完成任务的代码。

数据结构的核心就是,代码容易写,思考最难想的一个学习过程,由此可见画图在帮助我们理清思路,规整代码写法的时候就尤为重要!


希望这篇博客能给读者在学习数据结构时提供一些帮助。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLO11改进 | 注意力机制 | 结合静态和动态上下文信息的注意力机制

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 上下文Transformer&#xff08;CoT&…

WPF中的布局

布局原则 1、不显式设置元素大小。 2、不使用绝对定位。 元素应该根据容器的内容来进行排列。绝对定位在开发前期会带来一些便捷&#xff0c;但扩展性比较差。一旦显示器尺寸或分辨率发生改变&#xff0c;界面的显示效果可能会达不到预期的效果。 3、布局容器可以嵌套使用 常…

【Axure原型分享】标签管理列表

今天和大家分享通过标签管理列表的原型模板&#xff0c;包括增删改查搜索筛选排序分页翻页等效果&#xff0c;这个模板是用中继器制作的&#xff0c;所以使用也很方便&#xff0c;初始数据我们只要在中继器表格里填写即可&#xff0c;具体效果可以观看下方视频或者打开预览地址…

【经管】上市公司供应链金融数据(1990-2023年)

上市公司供应链金融是指上市公司利用其产业链核心地位&#xff0c;通过整合金融资源&#xff0c;为供应链上下游企业提供包括融资、结算、风险管理等在内的综合金融服务。为了衡量上市公司的供应链金融水平&#xff0c;参考周兰等&#xff08;2022&#xff09;的研究方法&#…

【C++入门篇 - 3】:从C到C++第二篇

文章目录 从C到C第二篇new和delete命名空间命名空间的访问 cin和coutstring的基本使用 从C到C第二篇 new和delete 在C中用来向系统申请堆区的内存空间 New的作用相当于C语言中的malloc Delete的作用相当于C语言中的free 注意&#xff1a;在C语言中&#xff0c;如果内存不够…

IBM Flex System服务器硬件监控指标解读

随着企业IT架构的日益复杂&#xff0c;服务器的稳定运行对于保障业务连续性至关重要。IBM Flex System作为一款模块化、可扩展的服务器解决方案&#xff0c;广泛应用于各种企业级环境中。为了确保IBM Flex System服务器的稳定运行&#xff0c;监控易作为一款专业的IT基础设施监…

git维护【.gitignore文件】

在工程下添加 .gitignore 文件【git忽略文件】 *.class .idea *.iml *.jar /*/target/更多&#xff1a; # Compiled class file *.class# Log file *.log *.imi *.lst# BlueJ files *.ctxt# Mobile Tools for Java (J2ME) .mtj.tmp/# Package Files # *.jar *.war *.nar *.ea…

【MySQL 保姆级教学】数据库基础(重点)(2)

目录 1. 什么是数据库1.1 数据库的定义1.2 mysql 和 mysqld1.3 文件和数据库 2. 数据库的分类3. 连接数据库3.1 数据库的安装3.2 连接服务器&#xff08;数据库&#xff09;3.3 服务器 数据库 表 三者的关系 4. 数据库-表 和目录-文件 的关系5. MySQL 框架6. SQL 分类7. 储存引…

DDoS攻击快速增长,如何在抗ddos防护中获得主动?

当下DDoS攻击规模不断突破上限。前段时间&#xff0c;中国首款3A《黑神话&#xff1a;悟空》也在一夜之内遭受到28万次攻击DDoS攻击&#xff0c;严重影响到全球玩家的游戏体验。Gcore发布的数据也显示了 DDoS攻击令人担忧的趋势&#xff0c;尤其是峰值攻击已增加到了令人震惊的…

CNN-GRU时序预测 | MATLAB实现CNN-GRU卷积门控循环单元时间序列预测

时序预测 | MATLAB实CNN-GRU卷积门控循环单元时间序列预测 目录 时序预测 | MATLAB实CNN-GRU卷积门控循环单元时间序列预测预测效果基本介绍模型描述程序设计参考资料预测效果 基本介绍 本次运行测试环境MATLAB2020b 提出了一种基于卷积神经网络(Convolutional Neural Network…

生成式专题的第一节课---GAN图像生成

一、GAN的起源与发展 1.GAN的起源 GAN &#xff08;生成式对抗网络&#xff09;诞生于 2014 年&#xff0c;由 Ian Goodfellow 提出&#xff0c;是用于生成数据的深度学习模型&#xff0c;创新点是对抗性训练&#xff0c;即生成器与判别器的竞争关系&#xff0c;为图像生成、…

【网络安全】利用XSS、OAuth配置错误实现token窃取及账户接管 (ATO)

未经许可,不得转载。 文章目录 正文正文 目标:target.com 在子域sub1.target.com上,我发现了一个XSS漏洞。由于针对该子域的漏洞悬赏较低,我希望通过此漏洞将攻击升级至app.target.com,因为该子域的悬赏更高。 分析认证机制后,我发现: sub1.target.com:使用基于Cook…

DBA | 如何将 .mdf 与 .ldf 的数据库文件导入到SQL Server 数据库中?

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] 原文链接&#xff1a;DBA | 如何将 .mdf 与 .ldf 的数据库文件导入到SQL Server 数据库中? 如何将 (.mdf) 和 (.ldf) 的SQL Server 数据库文件导入到当前数据库中? Step 1.登录到 Sql Server 服…

Springboot——使用poi实现excel动态图片导入解析

文章目录 前言依赖引入导入实现方式一方式二 导出参考 前言 最近要实现一个导入导出的功能点&#xff0c;需要能将带图片的列表数据导出到excel中&#xff0c;且可以导入带图片的excel列表数据。 考虑到低代码平台的表头与数据的不确定性&#xff0c;技术框架上暂定使用Apach…

线性代数在大一计算机课程中的重要性

线性代数在大一计算机课程中的重要性 线性代数是一门研究向量空间、矩阵运算和线性变换的数学学科&#xff0c;在计算机科学中有着广泛的应用。大一的计算机课程中&#xff0c;线性代数的学习为学生们掌握许多计算机领域的关键概念打下了坚实的基础。本文将介绍线性代数的基本…

C++一个很好的计时方法

C一个很好的计时方法 //记时LARGE_INTEGER t1;LARGE_INTEGER t2;LARGE_INTEGER f;QueryPerformanceFrequency(&f);QueryPerformanceCounter(&t1);Sleep(100);QueryPerformanceCounter(&t2);double time;time (double)(t2.QuadPart-t1.QuadPart)/(double)f.QuadPar…

【Flutter】合并多个流Stream

1.说明 无意间发现了一个好用的库rxdart&#xff0c;它为 Dart 的 Stream 添加了额外的功能。 2.功能 &#xff08;1&#xff09;合并多个流Stream 借助Rx.combineLatest2()合并两个流stream1和stream2。 注意&#xff1a;如果dart文件中同时使用了getx&#xff0c;需要隐…

UE4 材质学习笔记03(翻书(Flipbook)动画/环境混合)

一.FlipBook Animation 如果你想让游戏以每秒30帧的速度运行&#xff0c;所有内容都必须在33毫秒内渲染出来&#xff0c; 如果你想让游戏以每秒60帧的速度运行的话&#xff0c;必须在16毫秒内。 所以当一个效果需要很多细节的时候&#xff0c;往往会离线创建它&#xff0c;然…

LLM | Tokenization 从原理与代码了解GPT的分词器

声明&#xff1a;以上内容全是学习Andrej Karpathy油管教学视频的总结。 --------------------------------------------------------------------------------------------------------------------------------- 大家好。在今天我们学习llm中的Tokenization&#xff0c;即分…