单链表的创建示意图(添加) 显示单向链表的分析
head节点: 不存放具体的数据, 作用就是表示单链表头next
HeroNode 数据next
HeroNode数据next
…
添加: 先创建一个head头节点, 作用就是表示单链表的头,后面我们每添加一个节点, 就直接加入到链表的最后
遍历: 通过一个辅助遍历, 帮助遍历整个链表
应用实例
使用带head头的单向链表实现 –水浒英雄排行榜管理
完成对英雄人物的增删改查操作, 注: 删除和修改,查找可以考虑学员独立完成,也可带学员完成
第一种方法在添加英雄时,直接添加到链表的尾部
package DataStructures; public class SingleLinkedList { 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,"依依", "落落"); // 创建要给链表 SingleLinkedListD singleLinkedListD = new SingleLinkedListD(); // 加入 singleLinkedListD.add(hero1); singleLinkedListD.add(hero2); singleLinkedListD.add(hero3); singleLinkedListD.add(hero4); // 显示 singleLinkedListD.list(); } } // 定义SingleLinked 管理我们的英雄 class SingleLinkedListD { //先初始化一个头节点, 头节点不要动, private HeroNode head = new HeroNode(0,"",""); public void add(HeroNode heroNode) { //因为head节点不能动, 因此我们需要一个辅助变量temp HeroNode temp = head; // 遍历链表, 找到最后 while(true) { // 找到链表的最后 if (temp.next == null) { break; } // 如果没有找到最后,就将temp后移 temp = temp.next; } // 当退出while循环时, temp就指向了链表的最后 // 将最后这个节点的next 指向 新的节点 temp.next = heroNode; } //显示链表(遍历) 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 , 每个HeroNode 对象就是一个节点 class HeroNode { public int no; public String name; public String nickname; public HeroNode next; // 指向下一个节点 // 构造器 public HeroNode(int no, String hName, String hNickname) { this.no = no; this.name = hName; this.nickname = hNickname; } // 为了显示方法, 我们重新toString @Override public String toString() { return "HeroNode{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname; } }
第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
package DataStructures; public class SingleLinkedList { 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,"依依", "落落"); // 创建要给链表 SingleLinkedListD singleLinkedListD = new SingleLinkedListD(); // 加入 // singleLinkedListD.add(hero1); // singleLinkedListD.add(hero2); // singleLinkedListD.add(hero3); // singleLinkedListD.add(hero4); // 加入按照编号的顺序 singleLinkedListD.addByOrder(hero1); singleLinkedListD.addByOrder(hero2); singleLinkedListD.addByOrder(hero3); singleLinkedListD.addByOrder(hero4); singleLinkedListD.addByOrder(hero3); // 显示 singleLinkedListD.list(); } } // 定义SingleLinked 管理我们的英雄 class SingleLinkedListD { //先初始化一个头节点, 头节点不要动, private HeroNode head = new HeroNode(0,"",""); public void add(HeroNode heroNode) { //因为head节点不能动, 因此我们需要一个辅助变量temp HeroNode temp = head; // 遍历链表, 找到最后 while(true) { // 找到链表的最后 if (temp.next == null) { break; } // 如果没有找到最后,就将temp后移 temp = temp.next; } // 当退出while循环时, temp就指向了链表的最后 // 将最后这个节点的next 指向 新的节点 temp.next = heroNode; } // 第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示) public void addByOrder (HeroNode heroNode) { // 因为头节点不能动, 因此我们仍然通过一个辅助指针(变量) 来帮助找到添加的位置 //因为单链表, 因此我们找的temp 是位于添加位置的前一个节点, 否则插入不了 HeroNode temp = head; boolean flag = false; // flag标志添加的编号是否存在, 默认为false while(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; // 后移, 遍历当前链表 } // 判断flag 的值 if (flag) { // 不能添加,说明编号存在 System.out.println("准备插入的英雄编号%d已经存在了, 不能加入\n" + heroNode.no); } else { // 插入到链表中 temp的后面 heroNode.next = temp.next; temp.next = heroNode; } } //显示链表(遍历) 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 , 每个HeroNode 对象就是一个节点 class HeroNode { public int no; public String name; public String nickname; public HeroNode next; // 指向下一个节点 // 构造器 public HeroNode(int no, String hName, String hNickname) { this.no = no; this.name = hName; this.nickname = hNickname; } // 为了显示方法, 我们重新toString @Override public String toString() { return "HeroNode{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname; } }
修改链表
package DataStructures;
public class SingleLinkedList {
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,"依依", "落落");
// 创建要给链表
SingleLinkedListD singleLinkedListD = new SingleLinkedListD();
// 加入
// singleLinkedListD.add(hero1);
// singleLinkedListD.add(hero2);
// singleLinkedListD.add(hero3);
// singleLinkedListD.add(hero4);
// 加入按照编号的顺序
singleLinkedListD.addByOrder(hero1);
singleLinkedListD.addByOrder(hero2);
singleLinkedListD.addByOrder(hero3);
singleLinkedListD.addByOrder(hero4);
singleLinkedListD.addByOrder(hero3);
//显示
singleLinkedListD.list();
HeroNode newHeroNode = new HeroNode(2,"文","雨~~");
singleLinkedListD.update(newHeroNode);
System.out.println("修改后的链表情况");
singleLinkedListD.list();
}
}
// 定义SingleLinked 管理我们的英雄
class SingleLinkedListD {
//先初始化一个头节点, 头节点不要动,
private HeroNode head = new HeroNode(0,"","");
public void add(HeroNode heroNode) {
//因为head节点不能动, 因此我们需要一个辅助变量temp
HeroNode temp = head;
// 遍历链表, 找到最后
while(true) {
// 找到链表的最后
if (temp.next == null) {
break;
}
// 如果没有找到最后,就将temp后移
temp = temp.next;
}
// 当退出while循环时, temp就指向了链表的最后
// 将最后这个节点的next 指向 新的节点
temp.next = heroNode;
}
// 第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
public void addByOrder (HeroNode heroNode) {
// 因为头节点不能动, 因此我们仍然通过一个辅助指针(变量) 来帮助找到添加的位置
//因为单链表, 因此我们找的temp 是位于添加位置的前一个节点, 否则插入不了
HeroNode temp = head;
boolean flag = false; // flag标志添加的编号是否存在, 默认为false
while(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; // 后移, 遍历当前链表
}
// 判断flag 的值
if (flag) { // 不能添加,说明编号存在
System.out.println("准备插入的英雄编号%d已经存在了, 不能加入\n" + heroNode.no);
} else {
// 插入到链表中 temp的后面
heroNode.next = temp.next;
temp.next = heroNode;
}
}
// 修改节点的信息, 根据no的编号来修改, 即no编号不能改
//说明
// 1. 根据newHeroNode 的no来修改即可
public void update(HeroNode newHeroNode) {
// 判断是否空
if (head.next == null) {
System.out.println("链表为空");
return;
}
// 根据需要修改的节点, 根据no编写
// 定义一个辅助变量
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("没有找到编号为%d 的节点, 不能修改\n" + newHeroNode.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;
}
}
}
// 定义HeroNode , 每个HeroNode 对象就是一个节点
class HeroNode {
public int no;
public String name;
public String nickname;
public HeroNode next; // 指向下一个节点
// 构造器
public HeroNode(int no, String hName, String hNickname) {
this.no = no;
this.name = hName;
this.nickname = hNickname;
}
// 为了显示方法, 我们重新toString
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname;
}
}
删除链表
从单链表中删除一个节点的思路
我们先找到需要删除的这个节点的前一个节点temp
temp.next = temp.next.next;
被删除的节点,将不会有其他引用指向, 会被垃圾回收机制回收
package DataStructures; public class SingleLinkedList { 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,"依依", "落落"); // 创建要给链表 SingleLinkedListD singleLinkedListD = new SingleLinkedListD(); // 加入 // singleLinkedListD.add(hero1); // singleLinkedListD.add(hero2); // singleLinkedListD.add(hero3); // singleLinkedListD.add(hero4); // 加入按照编号的顺序 singleLinkedListD.addByOrder(hero1); singleLinkedListD.addByOrder(hero2); singleLinkedListD.addByOrder(hero3); singleLinkedListD.addByOrder(hero4); singleLinkedListD.addByOrder(hero3); //显示 singleLinkedListD.list(); HeroNode newHeroNode = new HeroNode(2,"文","雨~~"); singleLinkedListD.update(newHeroNode); System.out.println("修改后的链表情况"); singleLinkedListD.list(); // 删除一个节点 singleLinkedListD.del(1); System.out.println("删除后的链表情况"); singleLinkedListD.list(); } } // 定义SingleLinked 管理我们的英雄 class SingleLinkedListD { //先初始化一个头节点, 头节点不要动, private HeroNode head = new HeroNode(0,"",""); public void add(HeroNode heroNode) { //因为head节点不能动, 因此我们需要一个辅助变量temp HeroNode temp = head; // 遍历链表, 找到最后 while(true) { // 找到链表的最后 if (temp.next == null) { break; } // 如果没有找到最后,就将temp后移 temp = temp.next; } // 当退出while循环时, temp就指向了链表的最后 // 将最后这个节点的next 指向 新的节点 temp.next = heroNode; } // 第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示) public void addByOrder (HeroNode heroNode) { // 因为头节点不能动, 因此我们仍然通过一个辅助指针(变量) 来帮助找到添加的位置 //因为单链表, 因此我们找的temp 是位于添加位置的前一个节点, 否则插入不了 HeroNode temp = head; boolean flag = false; // flag标志添加的编号是否存在, 默认为false while(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; // 后移, 遍历当前链表 } // 判断flag 的值 if (flag) { // 不能添加,说明编号存在 System.out.println("准备插入的英雄编号%d已经存在了, 不能加入\n" + heroNode.no); } else { // 插入到链表中 temp的后面 heroNode.next = temp.next; temp.next = heroNode; } } // 修改节点的信息, 根据no的编号来修改, 即no编号不能改 //说明 // 1. 根据newHeroNode 的no来修改即可 public void update(HeroNode newHeroNode) { // 判断是否空 if (head.next == null) { System.out.println("链表为空"); return; } // 根据需要修改的节点, 根据no编写 // 定义一个辅助变量 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("没有找到编号为%d 的节点, 不能修改\n" + newHeroNode.no); } } //删除节点 //思路 //1.head不能动 因此我们需要temp辅助节点找到待删除节点的前一个节点 // 2. 说明我们在比较时,时temp.next.no和需要删除的节点的no比较 public void del(int no) { HeroNode temp = head; boolean flag = false; // 标志是否找到待删除节点的 while (true) { if (temp.next == null) { //已经到链表的最后 break; } if (temp.next.no == no) { // 找到了待删除的前一个节点temp flag = true; break; } temp = temp.next;// temp后移 遍历 } //判断flag if (flag) { // 找到 // 可以删除 temp.next = temp.next.next; }else { System.out.println("要删除的%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; } } } // 定义HeroNode , 每个HeroNode 对象就是一个节点 class HeroNode { public int no; public String name; public String nickname; public HeroNode next; // 指向下一个节点 // 构造器 public HeroNode(int no, String hName, String hNickname) { this.no = no; this.name = hName; this.nickname = hNickname; } // 为了显示方法, 我们重新toString @Override public String toString() { return "HeroNode{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname; } }
版权声明:本文为qq_52330730原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。