Java高级系列文章前言
本文章涉及到数据结构与算法的知识,该知识属于Java高级阶段,通常为学习的二阶段,本系列文章涉及到的内容如下(橙色框选内容):
本文章核心是教学视频,所以属于个人笔记,非商用。
文章结构
标识
本系列文章中记录的数据结构与算法都会多多少少用到一些Java的API,这些API只会一笔带过,主要还是看逻辑思路。
大标题小标题文本内容和图片内容... 70%/30%图片说明(加重)逻辑思路和次要说明文本说明(普通文本)主要说明和补充
内容结构
大标题介绍英文单词关键字陈列(有时会省略)代码块...思路引入(概率出现小标题)思路解析(概率出现小标题)源码代码展示图文说明
双向链表
介绍
双向链表可以实现自我删除,在插入数据和删除数据时要比单向列表方便很多,和单列表并没有太大的区别。
英文单词关键字陈列
书写习惯:XxxYyyZzz(Java类驼峰语法)
格式:英文单词 -> 中文翻译 -> 空耳(个人习惯)
pre -> 前
思路引入
单向链表查找的方向只能是一个方向,而双向链表可以向前或前后查找,单向链表不能自我删除,需要靠辅助节点,双向链表则可以自我删除。
思路解析
本质上就是给单链表类增加了一个和next同类型的变量,该变量为pre,pre表示前缀/前面,在双向链表中表示该属性是当前节点的前一个节点,现在一个节点有前节点和后节点的属性,所以就是双向的。
源码
代码展示
package linkedlist;public class DoubleLinkedListDemo {public static void main(String[] args) {}
}
//创建一个双向链表的类
class DoubleLinkedList{//先初始化一个头节点,头节点的数据域不存放数据,头指针指向头节点private HeroNode2 head = new HeroNode2(0,"","");//返回头节点public HeroNode2 getHead(){return head;}//添加一个节点到双向链表public void add(HeroNode2 heroNode){//因为头节点不能动(头结点是一个不存储数据的标记节点,也可以附加链表信息)//因此我们需要一个辅助变量 -> tempHeroNode2 temp = head;//有个临时节点指向了head//遍历链表,找到最后while(true){//找到链表的最后了if(temp.next == null){//说明已经找到最后了break;}//如果没有找到最后,将temp后移为它的下一个节点,依次往后走temp = temp.next;}//当退出while循环时,temp就指向了链表的最后,并且让新节点的pre指向temp//形成一个双向链表temp.next = heroNode;heroNode.pre = temp;}//修改一个节点的内容public void update(HeroNode2 newHeroNode){//判断是否为空if(head.next==null){System.out.println("链表为空!");return;}//找到需要修改的节点,根据no编号//先定义一个辅助变量HeroNode2 temp = head.next;boolean flag = false;//表示是否找到该节点while(true){if(temp == null){break;//到链表的最后}if(temp.no == newHeroNode.no){//找到flag = true;break;}temp = temp.next;}//根据flag判断是否找到要修改的节点if(flag){temp.name = newHeroNode.name;temp.nickname = newHeroNode.nickname;}else{System.out.printf("没有找到编号%d的节点,不能修改\n",newHeroNode.no);}}//从双向链表中删除一个节点//说明//1.对于双向链表,我们可以直接找到要删除的这个节点,而不需要找到要删除节点的前一个节点//2.找到后,自我删除即可public void del(int delNo){//判断当前链表是否为空if(head.next == null){//空链表System.out.println("链表为空,无法删除");return;}HeroNode2 temp = head.next;//辅助变量(指针) 直接找本身boolean flag = false;//标志是否找到待删除节点while(true){if(temp == null){//已到链表最后break;}if(temp.no == delNo){//找到了待删除节点的前一个节点 temp ,此时temp是要删除节点的前一个节点!flag = true;break;}temp = temp.next;//temp后移才能实现遍历}//判断flagif(flag){//说明找到//可以删除temp.pre.next = temp.next;//让temp的前一个节点的下一个节点指向temp的下一个节点//如果是最后一个节点,就不需要指向下面这句话,否则会空指针异常if(temp.next!=null){temp.next.pre = temp.pre;//让temp的下一个节点的前一个节点指向temp的前一个节点}}else{System.out.printf("要删除的 %d 节点不存在!\n",delNo);}}//遍历双向链表的方法//显示链表[遍历]public void list(){//先判断链表是否为空if(head.next==null){System.out.println("链表为空!");return;}//因为头节点不能动,因此我们需要一个辅助变量来遍历HeroNode2 temp = head.next;while(true){//判断是否到链表最后if(temp == null){break;}//输出节点的信息System.out.println(temp);//将next后移temp = temp.next;}}
}
//定义HeroNode,每个HeroNode对象就是一个节点
class HeroNode2{public int no;//编号,Nopublic String name;//名字public String nickname;//昵称public HeroNode2 next;//指向下一个节点,默认为nullpublic HeroNode2 pre;//指向前一个节点,默认为null//构造器public HeroNode2(int heroNo,String heroName,String heroNickName){this.no = heroNo;this.name = heroName;this.nickname = heroNickName;}//为了显示方便,我们重写toString()方法@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", nickname='" + nickname + '\'' +'}';}
}
图文说明
由于双向链表和单向链表的区别不大,本文章并没有过多介绍。