单链表(single-linked list)
链表结构
- node包含data+next,指向下一个结点的地址。链式存储。
- 链表分为带头结点的链表和没有头结点的链表。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpz1sGoF-1617540529891)(2D972D2CC290432D8483C74C3E72B301)]
最后一个结点的next域是null。
应用实例
英雄排行榜,实现尾部插入和按排序插入,删,查,改。
分析
数据结构
- head节点:不存放具体的数据,next域指向HeroNode。
- HeroNode节点:包括数据和next域。
- 链表。
算法
类
HeroNode类,实现节点。包括data和next指针。一般为了防止输出node的时候把它后面的node都输出,去要重写tostring().
class HeroNode
{
int no;
String name;
String nickName;
HeroNode next;
@Override
public String toString(){
}
}
链表类SingleLinkedList,作用是创建头节点。里面有若干方法,可以实现节点的增删查改(删查改在后面实现)和遍历列表.
class SingleLinkedList
{
private HeroNode head = new HeroNode(0, "", "");
add(){
}//增
del(){
}//删
search(){
}//查
update(){
}//改
list(){
}//遍历
}
方法
因为头指针不能动,所以所有涉及遍历的方法(除了创建)都需要辅助变量temp。
- 创建:head头节点。
- 遍历:通过一个辅助变量来遍历整个链表。
- 添加:1)直接把节点加入到队尾,该方法需要遍历到队尾。2)按照编号依次插入,该方法需要一个辅助变量,查找到需要添加位置的前一个位置(因为这是单向链表。你找到后面了就找不到前面的node了,没法改他的指针了),比较的条件:temp.next.no>current.no.
- 删除:指定编号,查找到待删除节点的前一个节点,比较的是该节点下一个结点的编号和待删除结点的编号。找到后删除该节点。
- 查找:指定编号,遍历,找到该节点编号,输出该节点数据。
- 修改:指定编号,查找到待修改结点,对节点的属性进行修改。
对象
- 英雄节点:heronode。含有属性和next指针。
- 英雄链表:singleLinkedList。包含增删查改和遍历方法。
代码实现
插入
向尾部直接插入节点
思路分析
遍历到最后一个,把最后一个指针指向待加入节点。
算法实现
- main方法:
package linckedList;
public class SingleLinkedListDemo
{
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.add(hero1);
singleLinkedList.add(hero2);
singleLinkedList.add(hero3);
singleLinkedList.add(hero4);
//显示
singleLinkedList.list();
}
}
- 定义一个链表类SingleLinkedList,作用是创建头节点。里面有若干方法,可以实现节点的增删查改(删查改在后面实现)和遍历列表.
//定义一个类管理英雄
class SingleLinkedList
{
//初始化一个头结点,不能变化
private HeroNode head = new HeroNode(0, "", "");
//添加节点到单向链表
public void add(HeroNode heroNode)
{
//当不考虑编号的顺序时,找到最后节点,把最后节点的next域指向这个节点
//头节点不能动,所以需要一个辅助变量指向head
HeroNode temp = head;
//遍历链表,找到最后
while (true)
{
if (temp.next == null)
{
break;
}
//没有找到最后一个的时候temp后移。
temp = temp.next;
}
//退出while循环的时候,temp指向链表的最后
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对象就是一个节点。为了显示方便,重写了tostring()。
//定义一个HeroNode,每个HeroNode对象就是一个节点
class HeroNode
{
public int no;
public String name;
public String nickName;
public HeroNode next;//指向下一个节点
//构造器
public HeroNode(int hNo, String hName, String hNickName)
{
no = hNo;
name = hName;
nickName = hNickName;
}
//为了显示方便,重写tostring
@Override
public String toString()
{
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
按照顺序插入指定位置
思路分析
- 首先找到新添加节点的位置。通过一个辅助变量(指针)来实现。
- 该方法需要一个辅助变量,查找到需要添加位置的前一个位置(因为这是单向链表。你找到后面了就找不到前面的node了,没法改他的指针了),比较的条件:temp.next.no>current.no.
- 新的节点.next=temp.next
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z9YhpvzP-1617540529895)(41137CDF94AE4507AE3142F4B55D1E3D)] - temp.next=新的节点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ApyHgLS1-1617540529896)(A99F42B14AEE4A44813A35E96B9F9500)]
算法实现
注:就加了一个方法addByOrder,其他除了main方法做测试,把插入顺序打乱和添加了一个重复no之外都没有变化。下面只列出main方法和addByOrder方法,其他的一样,不赘述。
- main方法
public class SingleLinkedListDemo
{
public static void main(String[] args)
{
//测试
//创建节点
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3,