1、什么是单链表
说到单链表,顾名思义,链表链表,跟我们现实生活中的铁链子很像,铁链子上有很多的铁块,铁块就对应了结点,1条铁链子就是1个单链表。每1个结点(铁块)包含2个部分
- 保存了data值(如上图的4、15、7、40)
- 指向了下1个结点的地址,也就是上方的椭圆
注意:
- 第1个结点被称为表头、头结点,知道了头结点就可以访问到整个链表。因为头结点保存了下1个结点的地址,下1个结点又保存了下下个结点的地址…
- 链表的最后1个结点,它指向的下1个地址为null
2、单链表如何创建
class ListNode{
//定义1个int型的属性,当做data
int val;
定义1个ListNode类型的属性,也就是它本身,也就是1个对象
ListNode next;
//构造方法,初始化val值
public ListNode(int x){
val = x;
}
}
首先我们创建1个ListNode类用来模拟链表,定义1个整形变量充当结点的data,每个结点都有1个data,在类中定义1个ListNode类的实例来充当结点的指向的下1个地址。这里可能有小伙伴不太懂了,我第一次看也没看懂,研究了一会才明白,举个栗子:
实例化1个ListNode对象,ListNode listnode= new ListNode();
此时,这个listnode对象有2个属性值(整形的val,和ListNode型的next)
那么这个next也是1个ListNode对象,那这个next也得有2个属性值吧…即这样循环下去,构成了单链表,啥时候结束呢,让最后1个结点的next =null就结束了。
3、单链表的基本操作(增删)
对于单链表的任何操作,都是从头向后访问的
- 链表的遍历
//获取链表的长度
public static int getLength(ListNode head){
//定义1个int,初始化链表长度=0
int length = 0;
//创建1个辅助节点,指向头结点,使用它来遍历链表
ListNode listNode = head;
//开始遍历链表
while (listNode != null){
length++;
//移动辅助节点
listNode = listNode.next;
}
return length;
}
①链表的插入
链表的插入,可以插入到3个位置,表头,表中,表尾
- 表头插入
表头的插入相对是简单的,只需要将新节点.next指向表头结点(即指向head指针,即newNode.net=head)即可,然后再将head指针指向新节点 - 表中插入
表中插入的设计思想:先找到要插入位置的前1个结点,此时,插入位置的前1个结点.next是我们要插入位置的后1个结点,理解这点之后,我们就可以进行移动了
InsertNode.next = 前1个结点.next
前1个结点.next = InsertNode - 表尾插入
表尾插入就是把最后1个结点.next = null 即可
新增完整代码:
public static ListNode insertList(ListNode head, ListNode inertNode, int position){
//若链表为空,则插入的 就是 链表的头结点
if (head == null){
return inertNode;
}
//判断不能插入的情况,插入位置从1开始
//位置小于1,位置大于最后1个节点的后1个位置,比如长度是5,插入位置在7
int size = getLength(head);
if (position < 1 || position > size + 1){
System.out.println("抱歉,您插入的位置有误!");
return head;
}
//若插入的位置是1
if (position == 1){
inertNode.next = head;
head = inertNode;
return head;
}
//辅助结点
ListNode listNode = head;
int count = 1;
//若1 < y , y的位置就是y的位置
//如长度为7,position=8,则此时辅助节点的位置在7,即最后1个
//如长度为7,position = 3 ,则此时辅助节点的位置在2
while (count < position - 1){
listNode = listNode.next;
count++;
}
//若为最后一个,赋值为insertNode.next = null
inertNode.next = listNode.next;
listNode.next = inertNode;
return head;
}
②链表的删除
链表可以从首结点、中间结点、尾结点删除
- 删除头结点
删除头结点,让head指针= head.next即可 - 删除中间结点
删除表中结点,思路:先定位到要删除位置的前1个结点,让前1个结点指向要删除结点的指向的结点即可,即前1个结点.next = 前1个结点.next.next
- 删除尾结点
删除尾结点,类似于删除表中结点的一种特殊形式,只不过要删除的结点的前1个结点指向的是null。
删除完整代码:
//链表的删除
public static ListNode deleteNode(ListNode head,int position){
//若为空表,则直接返回
if (head == null){
return null;
}
int size = getLength(head);
if (position < 1 || position > size){
System.out.println("您删除的位置有误!");
return head;
}
if (position ==1){
head = head.next;
}else {
//构建辅助结点
ListNode listNode = head;
int count = 1;
//遍历,把辅助节点定位到要删除位置的前1个
while (count < position -1){
listNode = listNode.next;
count++;
}
listNode.next = listNode.next.next;
}
return head;
}