单链表Java代码实现,以水浒英雄链表为例

文章目录

  • 单链表Java代码实现,以水浒英雄链表为例
    • 定义一个英雄链表
    • 定义一个SingleLinkedList 用于管理结点
      • 初始化头结点以及添加结点到单链表
      • 显示链表
      • 添加元素到指定位置
      • 修改结点信息
      • 删除元素
    • 测试
    • 结果
    • 完整代码
  • 双向链表
    • 定义节点,注意,此时要添加一个pre信息
    • 初始化头结点以及遍历双向链表
    • 向双向链表最后添加元素
    • 修改一个结点的内容(和单链表相同)
    • 删除一个结点
    • 完整代码
    • 执行结果

单链表 :元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
┌───┬───┐
│data │next │
└───┴───┘
头结点不存放数据,但存放着下一个指针的地址,其他每个指针服从上面所示存储关系,最后一个指针指向null。

定义一个英雄链表

/*** 定义结点, 每个对象是一个结点**/class HeroNode {public int no;public String name;public String nickname;public HeroNode next;   //指向下一个结点/*** 构造器* @param no* @param name* @param nickname*/public HeroNode(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}/*** 为了显示方便,重写toString* @return*/@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", nickname='"+ nickname + "}";}

定义一个SingleLinkedList 用于管理结点

初始化头结点以及添加结点到单链表

添加时要遍历到最后一个结点,然后将指针指向要添加的结点即heroNode

//初始化头结点,头结点不要动,不存放数据private HeroNode head = new HeroNode(0, "", "");/*** 添加节点到单向列表* @param heroNode*/public void add(HeroNode heroNode) {// head不能动,需要辅助遍历tempHeroNode temp = head;while (true) {// 找到链表最后if (temp.next == null) {break;}//如果没有找到最后,将temp后移temp = temp.next;}//退出while时,temp就指向了链表的最后// 将最后这个节点的next指向新的结点temp.next = heroNode;}

显示链表

只要结点的next不指向空,那么就输出这个结点的信息,否则输出最后一个结点的信息然后结束。

    /**** 显示链表*/public void list() {//判断链表是否为空if (head.next == null) {System.out.println("链表为空");return;}//头节点不能动,需要辅助变量遍历HeroNode temp = head.next;while (true) {// 判断是否到链表最后if (temp == null) {break;}//输出结点信息System.out.println(temp);//temp后移temp = temp.next;}}

添加元素到指定位置

当添加元素到链表中间,涉及到如下操作,头一个结点指针指向新结点,新结点的指针指向原先的后一个结点。即
heroNode.next = temp.next;
temp.next = heroNode;

    /*** 添加元素到指定位置* @param heroNode*/public void addByOrder(HeroNode heroNode) {//因为是单链表,所以我们的temp是添加位置的前一个结点HeroNode temp = head;boolean flag = false; //标志添加的编号是否存在,默认为falsewhile (true) {if (temp.next == null) { //temp已经位于链表的最后break;}if (temp.next.no > heroNode.no) { //位置找到,在temp的后面插入break;} else if (temp.next.no == heroNode.no) { //说明希望添加的heroNode编号已然存在flag = true;break;}temp = temp.next; //后移,遍历当前链表}if (flag) {System.out.printf("准备插入的元素编号%d 已经存在了,不能加入\n", heroNode.no);} else {heroNode.next = temp.next;temp.next = heroNode;}}

修改结点信息

注意判断条件,修改信息只是简单的赋值语句

 /*** 修改结点的信息* @param newHeroNode*/public void update(HeroNode newHeroNode) {//判断是否为空if (head.next == null) {System.out.println("链表为空");return;}HeroNode 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.println("没有找到需要修改的结点的信息");}}

删除元素

例如我们要把刚才添加的元素删除,
只需把next重新指向原先的后一个元素

 /** 删除元素* @param no**/public void del(int no) {HeroNode temp = head;boolean flag = false;while (true) {if (temp.next == null) { //已到链表最后break;}if (temp.next.no == no) {//找到待删除结点的前一个结点tempflag = true;break;}temp = temp.next; //temp后移}if(flag) { //找到temp.next = temp.next.next;} else{System.out.printf("要删除的%d 结点不存在\n",no);}}

测试

        //测试HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");HeroNode hero2 = new HeroNode(2, "卢俊义", "王齐麟");HeroNode hero3 = new HeroNode(3, "吴用", "智多星");HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");//创建链表SingleLinkedList singleLinkedList = new SingleLinkedList();// 加入singleLinkedList.addByOrder(hero1);singleLinkedList.addByOrder(hero2);singleLinkedList.addByOrder(hero3);singleLinkedList.addByOrder(hero4);//显示singleLinkedList.list();//修改测试HeroNode newHeroNode = new HeroNode(2, "小卢", "王齐麟");singleLinkedList.update(newHeroNode);System.out.println("修改后的链表情况");singleLinkedList.del(3);//显示singleLinkedList.list();

结果

HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='王齐麟}
HeroNode{no=3, name='吴用', nickname='智多星}
HeroNode{no=4, name='林冲', nickname='豹子头}
修改后的链表情况
HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='小卢', nickname='王齐麟}
HeroNode{no=4, name='林冲', nickname='豹子头}

完整代码

public class LinkedList {public static void main(String[] args) {//测试HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");HeroNode hero2 = new HeroNode(2, "卢俊义", "王齐麟");HeroNode hero3 = new HeroNode(3, "吴用", "智多星");HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");//创建链表SingleLinkedList singleLinkedList = new SingleLinkedList();// 加入singleLinkedList.addByOrder(hero1);singleLinkedList.addByOrder(hero2);singleLinkedList.addByOrder(hero3);singleLinkedList.addByOrder(hero4);//显示singleLinkedList.list();//修改测试HeroNode newHeroNode = new HeroNode(2, "小卢", "王齐麟");singleLinkedList.update(newHeroNode);System.out.println("修改后的链表情况");singleLinkedList.del(3);//显示singleLinkedList.list();}
}// 定义SingleLinkedList 管理英雄class SingleLinkedList {//初始化头结点,头结点不要动,不存放数据private HeroNode head = new HeroNode(0, "", "");/*** 添加节点到单向列表* @param heroNode*/public void add(HeroNode heroNode) {// head不能动,需要辅助遍历tempHeroNode temp = head;while (true) {// 找到链表最后if (temp.next == null) {break;}//如果没有找到最后,将temp后移temp = temp.next;}//退出while时,temp就指向了链表的最后// 将最后这个节点的next指向新的结点temp.next = heroNode;}/*** 添加元素到指定位置* @param heroNode*/public void addByOrder(HeroNode heroNode) {//因为是单链表,所以我们的temp是添加位置的前一个结点HeroNode temp = head;boolean flag = false; //标志添加的编号是否存在,默认为falsewhile (true) {if (temp.next == null) { //temp已经位于链表的最后break;}if (temp.next.no > heroNode.no) { //位置找到,在temp的后面插入break;} else if (temp.next.no == heroNode.no) { //说明希望添加的heroNode编号已然存在flag = true;break;}temp = temp.next; //后移,遍历当前链表}if (flag) {System.out.printf("准备插入的元素编号%d 已经存在了,不能加入\n", heroNode.no);} else {heroNode.next = temp.next;temp.next = heroNode;}}/*** 修改结点的信息* @param newHeroNode*/public void update(HeroNode newHeroNode) {//判断是否为空if (head.next == null) {System.out.println("链表为空");return;}HeroNode 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.println("没有找到需要修改的结点的信息");}}/** 删除元素* @param no**/public void del(int no) {HeroNode temp = head;boolean flag = false;while (true) {if (temp.next == null) { //已到链表最后break;}if (temp.next.no == no) {//找到待删除结点的前一个结点tempflag = true;break;}temp = temp.next; //temp后移}if(flag) { //找到temp.next = temp.next.next;} else{System.out.printf("要删除的%d 结点不存在\n",no);}}/**** 显示链表*/public void list() {//判断链表是否为空if (head.next == null) {System.out.println("链表为空");return;}//头节点不能动,需要辅助变量遍历HeroNode temp = head.next;while (true) {// 判断是否到链表最后if (temp == null) {break;}//输出结点信息System.out.println(temp);//temp后移temp = temp.next;}}
}/*** 定义结点, 每个对象是一个结点**/class HeroNode {public int no;public String name;public String nickname;public HeroNode next;   //指向下一个结点/*** 构造器* @param no* @param name* @param nickname*/public HeroNode(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}/*** 为了显示方便,重写toString* @return*/@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", nickname='"+ nickname + "}";}
}

双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继直接前驱。

定义节点,注意,此时要添加一个pre信息

/*定义结点, 每个对象是一个结点*/
class HeroNode2 {public int no;public String name;public String nickname;public HeroNode2 next;   //指向下一个结点public HeroNode2 pre;/** 构造器*/public HeroNode2(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}/*** 为了显示方便,重写toString** @return*/@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", nickname='" + nickname + "}";}
}

初始化头结点以及遍历双向链表

//初始化一个头结点,不存放具体数据private HeroNode2 head = new HeroNode2(0, "", "");/*返回头结点*/public HeroNode2 getHead() {return head;}/*遍历双向链表*/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);//temp后移temp = temp.next;}}

向双向链表最后添加元素

将原先最后一元素的next指向新结点,同时该结点指向前一结点

/*添加节点到双向列表的最后*/public void add(HeroNode2 heroNode) {// head不能动,需要辅助遍历tempHeroNode2 temp = head;while (true) {// 找到链表最后if (temp.next == null) {break;}//如果没有找到最后,将temp后移temp = temp.next;}//退出while时,temp就指向了链表的最后//形成一个双向链表temp.next = heroNode;heroNode.pre = temp;}

修改一个结点的内容(和单链表相同)

/*修改一个结点的内容,和单向链表一样*/public void update(HeroNode2 newHeroNode) {//判断是否为空if (head.next == null) {System.out.println("链表为空");return;}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.println("没有找到需要修改的结点的信息");}}

删除一个结点

删除节点需要如图所示的指针转换操作,同时要用判断语句判断是否删除的是最后一个元素,如果是则不需要改变下一个结点的pre指针,因为下一个结点为空。

    /*删除一个结点*/public void del(int no) {//判断当前链表是否为空if (head.next == null) {System.out.println("链表为空,无法删除");return;}HeroNode2 temp = head.next; //辅助变量(指针)boolean flag = false;while (true) {if (temp == null) { //已到链表最后break;}if (temp.no == no) {//找到待删除结点的前一个结点tempflag = true;break;}temp = temp.next; //temp后移}if (flag) { //找到temp.pre.next = temp.next;//避免出现最后一个元素出现空指针异常,所以加上判断语句if (temp.next != null) {temp.next.pre = temp.pre;} else {System.out.printf("要删除的%d 结点不存在\n", no);}}}

完整代码

public class LinkedList2 {public static void main(String[] args) {//testSystem.out.println("双向链表测试");//创建节点HeroNode2 hero1 = new HeroNode2(1, "宋江", "及时雨");HeroNode2 hero2 = new HeroNode2(2, "卢俊义", "王齐麟");HeroNode2 hero3 = new HeroNode2(3, "吴用", "智多星");HeroNode2 hero4 = new HeroNode2(4, "林冲", "豹子头");//创建一个双向链表doublelinkedlist doublelinkedlist = new doublelinkedlist();doublelinkedlist.add(hero1);doublelinkedlist.add(hero2);doublelinkedlist.add(hero3);doublelinkedlist.add(hero4);doublelinkedlist.list();//修改HeroNode2 newHeroNode = new HeroNode2(2,"公孙胜","入云龙");System.out.println("修改后~~~~");doublelinkedlist.list();//删除doublelinkedlist.del(3);System.out.println("删除后~~~~");doublelinkedlist.list();}
}/*
定义一个双向链表*/
class doublelinkedlist {//初始化一个头结点,不存放具体数据private HeroNode2 head = new HeroNode2(0, "", "");/*返回头结点*/public HeroNode2 getHead() {return head;}/*遍历双向链表*/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);//temp后移temp = temp.next;}}/*添加节点到双向列表的最后*/public void add(HeroNode2 heroNode) {// head不能动,需要辅助遍历tempHeroNode2 temp = head;while (true) {// 找到链表最后if (temp.next == null) {break;}//如果没有找到最后,将temp后移temp = temp.next;}//退出while时,temp就指向了链表的最后//形成一个双向链表temp.next = heroNode;heroNode.pre = temp;}/*修改一个结点的内容,和单向链表一样*/public void update(HeroNode2 newHeroNode) {//判断是否为空if (head.next == null) {System.out.println("链表为空");return;}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.println("没有找到需要修改的结点的信息");}}/*删除一个结点*/public void del(int no) {//判断当前链表是否为空if (head.next == null) {System.out.println("链表为空,无法删除");return;}HeroNode2 temp = head.next; //辅助变量(指针)boolean flag = false;while (true) {if (temp == null) { //已到链表最后break;}if (temp.no == no) {//找到待删除结点的前一个结点tempflag = true;break;}temp = temp.next; //temp后移}if (flag) { //找到temp.pre.next = temp.next;//避免出现最后一个元素出现空指针异常,所以加上判断语句if (temp.next != null) {temp.next.pre = temp.pre;} else {System.out.printf("要删除的%d 结点不存在\n", no);}}}
}/*定义结点, 每个对象是一个结点*/
class HeroNode2 {public int no;public String name;public String nickname;public HeroNode2 next;   //指向下一个结点public HeroNode2 pre;/** 构造器*/public HeroNode2(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}/*** 为了显示方便,重写toString** @return*/@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", nickname='" + nickname + "}";}
}

执行结果

双向链表测试
HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='王齐麟}
HeroNode{no=3, name='吴用', nickname='智多星}
HeroNode{no=4, name='林冲', nickname='豹子头}
修改后~~~~
HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='王齐麟}
HeroNode{no=3, name='吴用', nickname='智多星}
HeroNode{no=4, name='林冲', nickname='豹子头}
删除后~~~~
HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='王齐麟}
HeroNode{no=4, name='林冲', nickname='豹子头}Process finished with exit code 0

[Java数据结构][3]单链表以及双向链表Java代码实现相关推荐

  1. Java数据结构——用单链表编写一个简易通讯录

    Java数据结构--用单链表编写一个简易通讯录 1.定义线性表的抽象数据类型(接口) 2.定义单链表的结点Node类 3.定义数据域中的联系人Person类 4.编写顺序表(类) 5.编写测试程序(m ...

  2. Java数据结构之单链表——day03

    1. 目的:使用Java实现一个简单的链表 链表的存储对象为自定义Hero类的实例化: 定义链表的节点类HeroNode: 定义链表类SingleLinkedList: 链表类SingleLinked ...

  3. Java数据结构之单链表下

    单链表的第二种添加可以按照编号顺序添加(如果这个编号的已存在也会提示该节点已存在). 先来分析一下不考虑编号顺序时,我们如何做: 1.找到当前链表的最后节点 2.将最后这个节点的next指向新的节点 ...

  4. Java数据结构3_单链表 Linked List

    链表(Linked List)介绍 链表是有序的列表,但是它在内存中的存储如下: 链表是以节点的方式来存储 每个节点包含data域,next域:指向下一个节点 如上图,发现链表的各个节点不一定是连续存 ...

  5. java数据结构之单链表逆置算法

    单链表逆置算法1 设计思想:在链表类中新加成员方法getNode(int i),用来获取指定位置的节点,新建一个空单链表,将原链表的每个节点按照从后往前的顺序依次取出,再把节点的数据依次添加到新的链表 ...

  6. 数据结构:单链表和双向链表

    1.链表 链表是有序的列表,但是它在内存中是存储如下 小结: 链表是以节点的方,来存储是链式存储 每个节点包含data域,next域:指向下一个节点 如图:发现链表的各个节点不一定是连续存储 链表分带 ...

  7. 图解Java数据结构之环形链表

    本篇文章介绍数据结构中的环形链表. 介绍 环形链表,类似于单链表,也是一种链式存储结构,环形链表由单链表演化过来.单链表的最后一个结点的链域指向NULL,而环形链表的建立,不要专门的头结点,让最后一个 ...

  8. 数据结构,单链表讲解,并使用Java代码实现单链表增删改查【尾部添加,中间插入、修改节点、删除节点、展示链表】

    文章目录 单链表 什么是单链表,链式存储结构详解 链表的节点 头节点,头指针和首元节点 单链表的实现 1.尾部添加新节点 思路分析 代码实现 注意事项 2.按照编号插入新节点 思路分析 代码实现 注意 ...

  9. 「数据结构 | 链表」单链表、双向链表节点操作演示动画

    目录 1. 什么是链表 2. 链表数据结构 2.1 单链表数据结构(Java) 2.2 双向链表数据结构(Java) 3. 单链表操作动画 3.1 新增节点 3.2 删除节点 4. 双向链表操作动画 ...

最新文章

  1. 【踩坑记录】记一次MySQL主从复制延迟的坑
  2. showModalDialog跨域访问的解决
  3. 扩有mysql的磁盘_为提高MySQL性能而在磁盘IO方面的设置
  4. shandong‘s approach for doing thing
  5. 【JS】Vue.js实现简单的ToDoList(一)——前期准备
  6. windows 2008R2 无法安装操作系统补丁,或无法安装Sp1升级包的解决办法
  7. idea解决maven全局配置
  8. linux shell 等待输入_linux运维——基础篇
  9. Python3利用pymysql操作 MySQL
  10. float:left后,导航栏不左浮解决
  11. 加速包可能没用!12306屏蔽多个抢票软件
  12. lesson 7 strategies for efficient CUDA programming
  13. 【转】缺少servlet-api.jar包
  14. tomcat如何设置账号和密码
  15. Java中Collection接口
  16. matlab结构地震,结构地震反应解析递推格式的Matlab实现
  17. 模电实验——实验三 集成运算放大器的基本应用
  18. Unity3D坦克大战项目总结
  19. 计算机桌面的理解,电脑桌面的基础知识教程,教你认识电脑桌面
  20. html5接金币游戏源码,利用HTML5实现Canvas聚宝盆接金币游戏

热门文章

  1. 2021年中国网络安全产业分析报告》发布
  2. actor-critic学习
  3. 诚聘java开发工程师(中高级)-base地北京海淀区
  4. Ubuntu 直接回到桌面
  5. JavaWeb之Eclipse中使用Maven构建SpringMVC项目
  6. bat 安装zabbix agent
  7. 使用几何光学实现空间相对定位2.0(python+opencv)
  8. ZYNQ bring-up分析(bootrom+fsbl)
  9. Java 按时间排序
  10. python的turtle库画乔治