Java — 单链表
单链表介绍
单链表的理解应该可以分为两部分:链表中的节点和节点之间的联系。与数组的不同之处在于:数组在物理上的存储是连续的,但是链表在物理上的存储是分散的,它仅仅是在逻辑结构上连续(逻辑上的“一条龙”)。
- 对于链表中的节点可以看作一个存储单元,这个存储单元中包括两部分:数据域(或者叫数据块)和地址域(或者叫地址块)。数据域是用来保存当前节点的数据,地址域是用来指向下一个节点在哪的。
- 节点之间的联系体现在各个节点的地址域中。通过第一个节点的地址域可以知道第二个节点在哪,通过第二个节点的地址域可以知道第三个节点在哪,以此类推,可以构成一个完整的链式逻辑存储结构。
- 一般而言,链表是有头有尾的。链表头意味着链表的开始,一般会用一个空节点表示链表头;链表尾意味着链表的结束,一般都是用最后一个节点表示,比如上图的节点3node。
单链表的Java实现
1. 节点构造
可以通过构造节点类来实现链表中的节点,包括数据域和地址域。
// 节点
// 链表节点
class HeroNode{
// 数据域
public int num;
public String name;
public String nickName;
// 地址域
public HeroNode next;
// 构造函数
public HeroNode(int hNum, String hName, String hNickName){
this.num = hNum;
this.name = hName;
this.nickName = hNickName;
}
// 显示节点内容
@Override
public String toString() {
return "HeroNode[num = " + num + ", name = " + name + ", nickName = " + nickName + "]";
}
}
2. 构造单链表类
构造链表类是为了方便链表操作,比如添加或者删除节点、遍历链表等等。当然,首先是初始化一个头节点,作为链表头。
// 单链表
class SingleLinkedList{
// 初始化头节点
private HeroNode headNode = new HeroNode(0, "", "");
}
2.1 单链表操作:添加节点
构造addNode方法,直接将节点添加到当前链表的结尾。假设此时链表不为空,并且是直接添加节点,不考虑排序等其他操作。
// 添加节点到链表尾(不考虑排序)
public void addNode(HeroNode node){
HeroNode temp = headNode;
while (temp.next != null){
temp = temp.next;
}
temp.next = node;
}
2.2 单链表操作:删除节点
应当首先判断链表是否为空,假如操作的链表是空链表,则无法删除任何节点。若链表不为空,则删除指定的节点。这里是根据传入的数据域参数,在当前链表中遍历找到对应的相同节点,并删除。(程序前提是待删除的节点只有一个)
// 删除特定num的节点
public void deleteNode(int num){
if (headNode.next == null){
System.out.println("链表空,无节点可删除");
return;
}
HeroNode temp = headNode;
while (temp.next != null){
if (temp.next.num == num){
temp.next = temp.next.next;
return;
}
temp = temp.next;
}
System.out.println("没有查找到指定的节点");
}
2.3 单链表操作:插入节点
因为之前设计的节点的数据域中含有数值参数num,并且链表初始化时就已按num的大小顺序初始化。所以此处的程序实现的功能是按照num的大小顺序,在特定的位置插入节点。
// 按顺序插入节点
public void insertNode(HeroNode node){
HeroNode temp = headNode;
while (temp.next != null){
if (temp.next.num > node.num){
break;
}
temp = temp.next;
}
node.next = temp.next;
temp.next = node;
}
2.4 单链表操作:遍历并打印链表
// 遍历链表
public void showList(){
if (headNode.next == null){
System.out.println("链表为空");
return;
}
HeroNode temp = headNode.next;
while (temp != null){
System.out.println(temp.toString());
temp = temp.next;
}
}
总结
重点在于理解单链表的物理存储和逻辑结构的差别,在基础的链表操作中注意地址处理细节就好。