今天开始学习链表。虽说链表是很基础的内容,但是搞懂它还是费了我不少功夫。总而言之,我总结出以下笔记:
1.链表中的每个结点都有数据域和指针域,但是空链表的头结点的数据域和指针域为空,任何链表的尾结点的指针域为空
2.结点的地址是自身被创造出来时就带的,与结点的指针域区别。结点的指针域指向该结点的下一个结点,即指针域中保存的是下一个结点的地址(如果下一个结点存在的话)
3.定义结点时一般只定义带数据域的结点,结点的指针域由头结点或尾结点进行赋值,具体看创建链表的方式
4.头结点和尾结点的创建都是用无参构造函数
5.创建链表前必须先给头结点和尾结点赋值null,因为即使不带任何参数的结点也不会默认为null(虽然debug时里面写的是null,但是进不去空链表时的if语句,我也不知道为什么)
接下来实操建立单链表的两种方法:
public class CreateAndTransit {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
LinkList L = new LinkList(n,true);
for(int i=0;i<n;i++) {
System.out.print(L.head.data + " ");
L.head = L.head.next;//获取头结点的下一个结点,相当于遍历
}
}
}
//定义结点类
class Node {
public Object data;//定义结点的数据域
public Node next;//定义结点的指针域
//定义无参数的结点构造函数
public Node() {
this(null,null);
}
//定义只有数据域的结点构造函数
public Node(Object data) {
this(data,null);
}
//定义既有数据域也有指针域的结点构造函数
public Node(Object data,Node next) {
this.data = data;
this.next = next;
}
}
//定义单链表类
class LinkList extends Node{
public Node head;//定义头结点
//定义构造一个单链表的构造函数
public LinkList() {
head = new Node();//初始化头结点
}
//定义构造一个长度为n的单链表的构造函数,choice表示选择哪种方法
public LinkList(int n,boolean choice) {
this();//初始化头结点
if(choice) {
order(n);
}
else {
reserveOrder(n);
}
}
//用尾插法顺序建立单链表
public void order(int n) {
head = null;//将头结点置为null,使if语句起作用(未赋值的结点不会默认为null)
int index = 1;//index作为结点的数据域
for(int i=0;i<n;i++) {
Node newnode = new Node(index);//构造一个新结点
index++;
//判断链表是否为空(头结点为空时链表为空)
if(head == null) { //这里不能是head.next,因为空链表的头结点是没有指针域的
head = newnode;//当链表为空时给头结点的指针域赋新结点的地址
}
else {
//结点的地址和结点的指针域是不同的,结点的地址是创建结点时就有的,结点的指针域指向该结点的下一个结点,即结点的指针域里的是下一个结点的地址
newnode.next = head;//把头结点的地址赋给新结点的指针域,既新结点指向头结点,为了让新结点链接到链表的最前面
head = newnode;//这里再让新结点的地址赋给头结点,是为了让头结点再次成为最前面的结点
}
//该方法头结点一直在动,但最后头结点一定在最前面
}
}
//用头插法逆序建立单链表
public void reserveOrder(int n) {
Node tail = new Node();//该方法需要一个尾结点
head = tail = null;//将头结点和尾结点先置为null,使得if语句起作用
int index = 1;
for(int i=0;i<n;i++) {
Node newnode = new Node(index);
index++;
if(head == null) {
head = tail = newnode;//若链表为空,则头结点和尾结点都赋予新结点的地址
}
else {
tail.next = newnode;//新结点的地址赋给尾结点的指针域,表示尾结点指向新结点,使新结点链接到链表最后
tail = newnode;//将新结点的地址赋给尾结点的地址,表示将尾结点后移到最后
}
//该方法中头结点一直在最前不动,尾结点一直变化但是最后一定在最后面
}
}
}
此次记录到此结束。
2020.9.23