1.首先说说什么是单链表(官方解释)
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
以“结点的序列”表示线性表称作线性链表(单链表),单链表是链式存取的结构。
2.存储方法
链接方式存储的线性表简称为链表(Linked List)。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
3.结点结构
┌───┬───┐
│data │next │
└───┴───┘
data域--存放结点值的数据域
next域--存放结点的直接后继的地址(位置)的指针域(链域)
其实这里可以理解为data是数据,next相当于数组中的下标,比如你要找到数组中的第一个数据,就必须要找到下标0,这里如果要找data的下一个数据data2,就可以根据next(地址)找到对应数据
头节点,头指针和首元节点
一个完整的链表需要由以下几部分构成:
- 头指针:一个普通的指针,它的特点是永远指向链表第一个节点的位置。很明显,头指针用于指明链表的位置,便于后期找到链表并使用表中的数据;
- 节点:链表中的节点又细分为头节点、首元节点和其他节点:
- 头节点:其实就是一个不存任何数据的空节点,通常作为链表的第一个节点。对于链表来说,头节点不是必须的,它的作用只是为了方便解决某些实际问题;
- 首元节点:由于头节点(也就是空节点)的缘故,链表中称第一个存有数据的节点为首元节点。首元节点只是对链表中第一个存有数据节点的一个称谓,没有实际意义;
- 其他节点:链表中其他的节点;
因此,一个存储 {1,2,3}
的完整链表结构如图所示:
注意:链表中有头节点时,头指针指向头节点;反之,若链表中没有头节点,则头指针指向首元节点。
下面用代码实现插入(尾插法)和遍历
//单链表的创建与遍历
public class SingleLinkedListDemo {
public static void main(String[] args) {
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(5, "卢俊义", "玉麒麟");
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();
}
}
class SingleLinkedList{
//头结点,不能动,不存放具体的数据
private HeroNode head = new HeroNode(0,"","");
//找到当前链表的最后结点
//将最后这个结点的next指向新的结点
public void add(HeroNode heroNode){
//因为head结点不动,我们需要定义一个临时结点
HeroNode temp = head;
//遍历这个链表,找到最后
while (true) {
//列表为空,直接添加
if (temp.next == null) {
temp.next = heroNode;
break;
}
//比较大小,直接插入
if (temp.number <= heroNode.number && heroNode.number <= temp.next.number) {
heroNode.next = temp.next;
temp.next = heroNode;
break;
}
//如果没有找到,就继续找
temp = temp.next;
}
}
//遍历
public void list(){
//判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
//因为head不能动
HeroNode temp = head.next;
while (true) {
//判断是否到链表最后
if (temp == null) {
break;
}
//输出结点信息
System.out.println(temp);
//将temp后移
temp = temp.next;
}
}
}
class HeroNode {
public int number;//排名
public String name;//姓名
public String nickName;//绰号
public HeroNode next;//指针
public HeroNode(int number, String name, String nickName) {
this.number = number;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode{" +
"number=" + number +
", name='" + name + '\'' +
", nickName='" + nickName +
'}';
}
}