新闻详情

新闻详情

首页 / 资讯中心 / 详情

链表进阶2:双向链表的构建

发布时间:2026/10/1 2:40:33来源:尧图网络
链表进阶2:双向链表的构建
链表进阶2:双向链表的构建[TOC](链表进阶2:双向链表的构建) 这一版我没有引入尾部tail,后面会更新单向链表与双向链表引入尾部节点tail的章节;1.创建链表节点;2.头插法2.尾插3.中间位置插入4.头删5.尾删6.按下标删除7.按值删除8.判断元素是否存在循环遍历即可9.返回存在元素的下标循环遍历即可10.toString方法这一版我没有引入尾部tail,后面会更新单向链表与双向链表引入尾部节点tail的章节;1.创建链表节点;这个链表节点与先前的单向链表相比,多了一个prev指向前一个节点;classListNode{publicintval;publicListNodenext;publicListNodeprev;publicListNode(intval){this.valval;this.nextnull;this.prevnull;}}2.头插法1)首先要有头节点,判断是否为null,如果是,头节点指向新的节点;2)新节点指向head,head的前一个节点prev指向新节点;3)新节点变为头节点;publicListNodeheadnull;publicvoidaddFirst(intval){ListNodenewnodenewListNode(val);if(headnull){headnewnode;return;}newnode.nexthead;head.prevnewnode;headnewnode;}2.尾插1)创建一个尾部节点,头节点;2)当头节点为空时,全部指向新节点;3)不为空,尾部插入,还要更新tail尾部publicvoidaddLast(intval){LinkedNodenewnodenewLinkedNode(val);if(headnull){headnewnode;return;}LinkedNodecurhead;while(cur.next!null){curcur.next;}cur.nextnewnode;newnode.prevcur;}3.中间位置插入1)首先判断下标,我们需要写链表的尺寸大小;2)下标为0或者最后调用前面的头插与尾插;3) 找出要插入的位置,开始插入privateintsize(){if(headnull){return0;}intsize0;for(LinkedNodecurhead;cur!null;curcur.next){size;}returnsize;}publicvoidadd(intindex,intval){LinkedNodenewnodenewLinkedNode(val);intsizesize();if(index0||indexsize){thrownewIndexOutOfBoundsException(下标越界);}if(index0){addFirst(val);return;}if(indexsize){addLast(val);return;}LinkedNodecurhead;for(inti0;iindex-1;i){curcur.next;}newnode.nextcur.next;cur.next.prevnewnode;cur.nextnewnode;newnode.prevcur;}4.头删1)判断是不是头节点head为空或者只有一个节点;2)更新head3)注意head的prev指向一定要为nullpublicvoidremoveFirst(){if(headnull){return;}if(head.nextnull){headnull;return;}headhead.next;head.prevnull;}5.尾删1)先判断是不是为空,或者只有一个节点2)找到最后要删除的节点的上一个,让他指向空;3)删除节点的prev也要指向空;publicvoidremoveLast(){if(headnull){return;}if(head.nextnull){headnull;return;}LinkedNodetailhead;while(tail.next!null){tailtail.next;}LinkedNodeprevtail.prev;prev.nextnull;tail.prevnull;}6.按下标删除1)首先还是要判断下标;2)下标为0,为尾部特殊处理3)循环遍历找到要删除的元素;publicvoidremove(intindex){intsizesize();if(index0||indexsize){thrownewIndexOutOfBoundsException(下标越界);}if(index0){removeFirst();return;}if(indexsize-1){removeLast();return;}LinkedNodetoDeletehead;for(inti0;iindex;i){toDeletetoDelete.next;}LinkedNodeprevtoDelete.prev;prev.nexttoDelete.next;toDelete.next.prevprev;toDelete.nextnull;toDelete.prevnull;}7.按值删除1).通过循环遍历,找出要删除的值的节点,直接退出break;2).判断循环结束是否找到,没找到直接返回;3).最后考虑删除节点是否为尾部节点;publicvoidremoveByvalue(intval){if(headnull){return;}if(head.valval){removeFirst();return;}LinkedNodecurhead;for(;cur!null;curcur.next){if(cur.valval){break;}}if(curnull){return;}LinkedNodeprevcur.prev;LinkedNodenextcur.next;prev.nextcur.next;if(next!null){next.prevprev;}cur.nextnull;cur.prevnull;}8.判断元素是否存在循环遍历即可publicbooleancontains(intval){if(headnull){returnfalse;}for(LinkedNodecurhead;cur!null;curcur.next){if(cur.valval){returntrue;}}returnfalse;}9.返回存在元素的下标循环遍历即可publicintindexOf(intval){inti0;for(LinkedNodecurhead;cur!null;curcur.next,i){if(cur.valval){returni;}}return-1;}10.toString方法publicStringtoString(){if(headnull){returnnull;}StringBuilderstrnewStringBuilder();for(LinkedNodecurhead;cur!null;curcur.next){str.append(cur.val);if(cur.next!null){str.append(, );}}LinkedNodetailhead;while(tail.next!null){tailtail.next;}str.append(||);for(LinkedNodecurtail;cur!null;curcur.prev){str.append(cur.val);if(cur.prev!null){str.append(, );}}returnstr.toString();}publicclassTestToString{privatestaticintpass0,fail0;privatestaticvoidcheck(Stringname,Stringexpected,Stringactual){if(expectednull?actualnull:expected.equals(actual)){pass;System.out.println([PASS] name - \actual\);}else{fail;System.out.println([FAIL] name);System.out.println( expected: \expected\);System.out.println( actual : \actual\);}}publicstaticvoidmain(String[]args){MyDLinkedListemptynewMyDLinkedList();check(空链表,,empty.toString());MyDLinkedListonenewMyDLinkedList();one.addFirst(1);check(单节点 [1],1||1,one.toString());MyDLinkedListmultinewMyDLinkedList();multi.addLast(1);multi.addLast(2);multi.addLast(3);check(多节点 [1,2,3],1, 2, 3||3, 2, 1,multi.toString());MyDLinkedListafterHeadnewMyDLinkedList();afterHead.addLast(1);afterHead.addLast(2);afterHead.addLast(3);afterHead.removeFirst();check(头删后 [2,3],2, 3||3, 2,afterHead.toString());MyDLinkedListafterTailnewMyDLinkedList();afterTail.addLast(1);afterTail.addLast(2);afterTail.addLast(3);afterTail.removeLast();check(尾删后 [1,2],1, 2||2, 1,afterTail.toString());System.out.println(\n通过 pass失败 fail);}}
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

小红书短链原理与还原:解析xsec_token与跳转避坑 2026/10/1 3:28:04

小红书短链原理与还原:解析xsec_token与跳转避坑

1. 短链在小红书生态里的角色:为什么平台要用它1.1 复制出来的链接,为什么是一串短码最近在整理分享物料的时候,一个细节让我特别注意:从小红书App里复制的链接,经常是https://xhslink.com/m/xxxxx这样的短链&#xff…

阅读更多 →
MaxClaw更新:8G显存跑H3视频生成与量化避坑指南 2026/10/1 3:28:04

MaxClaw更新:8G显存跑H3视频生成与量化避坑指南

昨天打开 ComfyUI,照例点了一下 Manager 里的 Update All,列表里又跳出了 MiniMax 的 MaxClaw 更新提醒。顺手更新、重启、跑了一条 H3 视频生成的流程,整体体感比上一版顺了不少。作为从 H3 刚开源就在折腾量化版、研究 8G 显存能不能跑、还…

阅读更多 →
Git Worktree 详解:一个仓库多工作目录,并行开发与热修复的最佳实践 2026/10/1 3:28:04

Git Worktree 详解:一个仓库多工作目录,并行开发与热修复的最佳实践

你有没有碰到过这种局面:功能写到一半,测试那边说线上有个紧急 bug,五分钟就能修完,但要改的代码和你正在写的这块刚好重叠。commit 吧,进度没完成,commit message 都不知道怎么写;stash 吧&…

阅读更多 →
小红书短链全解析:从跳转原理到失效排查 2026/10/1 3:28:04

小红书短链全解析:从跳转原理到失效排查

现在做内容推广、社群运营的朋友,谁手里还没几张小红书短链呢?一张https://xhslink.com/m/开头的链接,就能把粉丝导到指定笔记,在评论区、私信、微信里发起来也干净利落。但很多人只知道“能跳转”,不清楚它背后的跳转…

阅读更多 →
AI代码生成工具实战:从选型到审查的团队落地经验 2026/10/1 3:28:04

AI代码生成工具实战:从选型到审查的团队落地经验

1. 为什么AI代码生成工具让人又爱又恨过去两年,AI代码生成工具从一个“实验室玩具”变成了很多团队研发流程里的常驻角色。我自己从最开始用Copilot补全变量名,到后来用AI agent直接写模块、补测试、改bug,前后折腾了一年多,踩过的…

阅读更多 →
模拟磁盘文件系统实战:从FAT表到文件操作的完整指南 2026/10/1 3:27:57

模拟磁盘文件系统实战:从FAT表到文件操作的完整指南

简介:这是一份操作系统课程设计的完整实现方案,面向需要完成磁盘文件系统模拟实验的高校学生。项目基于JavaFX开发,覆盖文件分配表、目录管理、磁盘调度算法、文件操作、错误处理与用户界面等核心模块,并配有详细的设计报告和关键…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉