一、单链表的介绍和内存布局
二、单链表的应用实例
(一)、添加到尾部
单链表的创建添加示意图:
代码实现:
package list;
//定义HerNode,每个HerNode对象是一个结点
public class HeroNode {
public int no;
public String name;
public String nickname;// 这是他的昵称
public HeroNode next;// 指向下一个节点
// 构造器
public HeroNode(int no, String name, String nickname) {
this.no=no;
this.name=name;
this.nickname=nickname;
}
//为了显示方法,我们重写toString方法
public String toString() {
//不用打印next,因为打印next会在输出第一个节点的时候就全输出
return "HerNode[no=" + no + ",name=" + name + ",nickname=" + nickname +"]";
}
}
package list;
//定义SingleLinkdeList 管理英雄
public class SingleLinkedList {
// 先初始化一个头结点,头结点不要动,不存放具体的数据
private HeroNode head = new HeroNode(0, "", "");
// 添加节点到单向链表
// 当不考虑编号顺序时
// 1.找到当前链表的最后节点
// 2.将最后这个节点next 指向 新的节点;
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;
}
}
}
package list;
public class LinkedList {
public static void main(String[] args) {
// 先创建一个节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "林冲", "豹子头");
//创建链表
SingleLinkedList singleLinkedList =new SingleLinkedList();
//加人
singleLinkedList.add(hero1);
singleLinkedList.add(hero2);
singleLinkedList.add(hero3);
//显示
singleLinkedList.list();
}
}
(二)、按顺序添加
单链表按顺序添加示意图:
按顺序添加代码演示:
package list;
//定义HerNode,每个HerNode对象是一个结点
public class HeroNode {
public int no;
public String name;
public String nickname;// 这是他的昵称
public HeroNode next;// 指向下一个节点
// 构造器
public HeroNode(int no, String name, String nickname) {
this.no=no;
this.name=name;
this.nickname=nickname;
}
//为了显示方法,我们重写toString方法
public String toString() {
//不用打印next,因为打印next会在输出第一个节点的时候就全输出
return "HerNode[no=" + no + ",name=" + name + ",nickname=" + nickname +"]";
}
}
package list;
//定义SingleLinkdeList 管理英雄
public class SingleLinkedList {
// 先初始化一个头结点,头结点不要动,不存放具体的数据
private HeroNode head = new HeroNode(0, "", "");
// 添加节点到单向链表
// 当不考虑编号顺序时
// 1.找到当前链表的最后节点
// 2.将最后这个节点next 指向 新的节点;
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 addSequentially(HeroNode heroNode) {
HeroNode temp = head;
boolean flag = false;//标志添加的编号是否存在,默认为false
while(true) {
if(temp.next==null) {//说明节点已经在链表的最后
break;
}
//temp.next.no指的是当前节点的下一个节点的编号
//因为借助了temp指针从链表自上而下的搜索大于添加的节点的编号
//如果下一个节点的编号大于添加节点的编号就添加在这个节点之前
else if(temp.next.no>heroNode.no) {//位置找到,就在temp的后面插入
break;
}
else if(temp.next.no==heroNode.no) {//说明希望添加的编号已经存在
flag=true;//说明编号存在
break;
}
temp=temp.next;
}
if(flag==true) {
System.out.println("不能添加,因为编号已经存在");
}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;
}
}
}
package list;
public class LinkedList {
public static void main(String[] args) {
// 先创建一个节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "林冲", "豹子头");
//创建链表
SingleLinkedList singleLinkedList =new SingleLinkedList();
//加人
//singleLinkedList.add(hero1);
//singleLinkedList.add(hero2);
//singleLinkedList.add(hero3);
//按顺序添加
singleLinkedList.addSequentially(hero3);
singleLinkedList.addSequentially(hero1);
singleLinkedList.addSequentially(hero2);
//显示
singleLinkedList.list();
}
}
三、单链表节点的修改
代码演示:
package list;
//定义HerNode,每个HerNode对象是一个结点
public class HeroNode {
public int no;
public String name;
public String nickname;// 这是他的昵称
public HeroNode next;// 指向下一个节点
// 构造器
public HeroNode(int no, String name, String nickname) {
this.no=no;
this.name=name;
this.nickname=nickname;
}
//为了显示方法,我们重写toString方法
public String toString() {
//不用打印next,因为打印next会在输出第一个节点的时候就全输出
return "HerNode[no=" + no + ",name=" + name + ",nickname=" + nickname +"]";
}
}
package list;
//定义SingleLinkdeList 管理英雄
public class SingleLinkedList {
// 先初始化一个头结点,头结点不要动,不存放具体的数据
private HeroNode head = new HeroNode(0, "", "");
// 添加节点到单向链表
// 当不考虑编号顺序时
// 1.找到当前链表的最后节点
// 2.将最后这个节点next 指向 新的节点;
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 addSequentially(HeroNode heroNode) {
HeroNode temp = head;
boolean flag = false;// 标志添加的编号是否存在,默认为false
while (true) {
if (temp.next == null) {// 说明节点已经在链表的最后
break;
}
// temp.next.no指的是当前节点的下一个节点的编号
// 因为借助了temp指针从链表自上而下的搜索大于添加的节点的编号
// 如果下一个节点的编号大于添加节点的编号就添加在这个节点之前
else if (temp.next.no > heroNode.no) {// 位置找到,就在temp的后面插入
break;
} else if (temp.next.no == heroNode.no) {// 说明希望添加的编号已经存在
flag = true;// 说明编号存在
break;
}
temp = temp.next;
}
if (flag == true) {
System.out.println("不能添加,因为编号已经存在");
} else {
// 插入到temp后边
heroNode.next = temp.next;
temp.next = heroNode;
}
}
// 修改节点的信息,根据no的编号来修改,即no编号不能改
// 根据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;//已经遍历完链表
}
else if(temp.no==newHeroNode.no) {
//找到
flag=true;
break;
}
temp=temp.next;
}
if(flag) {
temp.name=newHeroNode.name;
temp.nickname=newHeroNode.nickname;
}else {//没有找到
System.out.println("没有找到无法修改");
}
}
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;
}
}
}
package list;
public class LinkedList {
public static void main(String[] args) {
// 先创建一个节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "林冲", "豹子头");
//创建链表
SingleLinkedList singleLinkedList =new SingleLinkedList();
//加人
//singleLinkedList.add(hero1);
//singleLinkedList.add(hero2);
//singleLinkedList.add(hero3);
//按顺序添加
singleLinkedList.addSequentially(hero3);
singleLinkedList.addSequentially(hero1);
singleLinkedList.addSequentially(hero2);
//测试修改节点的代码
//先new一个节点,然后把这个节点传给update方法
HeroNode newHeroNode=new HeroNode(2,"师","程序员");
singleLinkedList.update(newHeroNode);
//显示
singleLinkedList.list();
}
}
四、节点的删除
思路分析:
代码演示:
package list;
//定义HerNode,每个HerNode对象是一个结点
public class HeroNode {
public int no;
public String name;
public String nickname;// 这是他的昵称
public HeroNode next;// 指向下一个节点
// 构造器
public HeroNode(int no, String name, String nickname) {
this.no=no;
this.name=name;
this.nickname=nickname;
}
//为了显示方法,我们重写toString方法
public String toString() {
//不用打印next,因为打印next会在输出第一个节点的时候就全输出
return "HerNode[no=" + no + ",name=" + name + ",nickname=" + nickname +"]";
}
}
package list;
//定义SingleLinkdeList 管理英雄
public class SingleLinkedList {
// 先初始化一个头结点,头结点不要动,不存放具体的数据
private HeroNode head = new HeroNode(0, "", "");
// 添加节点到单向链表
// 当不考虑编号顺序时
// 1.找到当前链表的最后节点
// 2.将最后这个节点next 指向 新的节点;
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 addSequentially(HeroNode heroNode) {
HeroNode temp = head;
boolean flag = false;// 标志添加的编号是否存在,默认为false
while (true) {
if (temp.next == null) {// 说明节点已经在链表的最后
break;
}
// temp.next.no指的是当前节点的下一个节点的编号
// 因为借助了temp指针从链表自上而下的搜索大于添加的节点的编号
// 如果下一个节点的编号大于添加节点的编号就添加在这个节点之前
else if (temp.next.no > heroNode.no) {// 位置找到,就在temp的后面插入
break;
} else if (temp.next.no == heroNode.no) {// 说明希望添加的编号已经存在
flag = true;// 说明编号存在
break;
}
temp = temp.next;
}
if (flag == true) {
System.out.println("不能添加,因为编号已经存在");
} else {
// 插入到temp后边
heroNode.next = temp.next;
temp.next = heroNode;
}
}
// 修改节点的信息,根据no的编号来修改,即no编号不能改
// 根据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;// 已经遍历完链表
} else if (temp.no == newHeroNode.no) {
// 找到
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.name = newHeroNode.name;
temp.nickname = newHeroNode.nickname;
} else {// 没有找到
System.out.println("没有找到无法修改");
}
}
// 修改节点的信息,根据no的编号来修改,即no不能改
// 根据newHeroNode 的no来修改即可
public void remove(int no) {
HeroNode temp = head;
boolean flag = false;
while (true) {
if (temp.next == null) {
break;
} else if (temp.next.no == no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
} else {
System.out.println("要删除的节点不存在");
}
}
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;
}
}
}
package list;
public class LinkedList {
public static void main(String[] args) {
// 先创建一个节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "林冲", "豹子头");
//创建链表
SingleLinkedList singleLinkedList =new SingleLinkedList();
//加人
//singleLinkedList.add(hero1);
//singleLinkedList.add(hero2);
//singleLinkedList.add(hero3);
//按顺序添加
singleLinkedList.addSequentially(hero3);
singleLinkedList.addSequentially(hero1);
singleLinkedList.addSequentially(hero2);
//测试修改节点的代码
//先new一个节点,然后把这个节点传给update方法
HeroNode newHeroNode=new HeroNode(2,"师","程序员");
singleLinkedList.update(newHeroNode);
//测试删除节点
singleLinkedList.remove(2);
//显示
singleLinkedList.list();
}
}