文章目录
一、链表是什么?
链表是一种数据结构,它由一系列的节点组成,每个节点都包含一个值和一个指向下一个节点的指针。链表中的节点是通过指针连接起来的,在内存中的存储位置可以是任意的,不要求连续。链表可以用来存储和表示线性数据,例如列表、栈、队列等。相对于数组,链表的优势在于可以动态地分配和释放存储空间,而且插入和删除元素的操作效率较高。
二、链表的相关概念
1.节点和头节点
在链表中,每个点都由值和指向下一个结点的地址组成的独立的单元,称为一个结点,有时也称为接点。
对于单链表,如果知道了第一个元素,就可以通过遍历访问整个链表,因此第一个结点最为重要,一般称为头结点。
2.虚拟结点
虚拟结点的概念其实就是一个结点dummyNode,其next指针指向head,也就是dummyNode.next=head.所以,当我们在算法里使用了虚拟结点,则要注意如果要获得head结点,应使用dummyNode.next.虚拟结点的作用主要是方便处理首部结点,否则就需要在代码里单独处理首部结点问题。
三、创建链表
/**
* 创建链表
* @author json-zhang
*/
public class ListNode {
private int index;
private ListNode next;
ListNode(int x){
index=x;
next=null;
}
ListNode listNode=new ListNode(1);
}
这里的index是当前节点的值,next存放的是下一个节点的地址。
四、链表的增删改查
1.遍历链表,获取链表长度
对于单链表,一定是从头结点开始,逐个向后访问。
/**
* 遍历链表,获取链表长度
* ListNode head 头结点
*/
public static int getListLength(ListNode head){
int length=0;
//创建头结点
ListNode listNode=head;
//当节点不为空时执行循环
while(listNode !=null){
//节点不为空,长度+1
length++;
//listNode指向当前节点的下一个节点
listNode=listNode.next;
}
//循环结束返回遍历的链表长度
return length;
}
2.链表的插入
单链表的插入分为头部,尾部和中部三种情况。
2.1 链表的头部插入法
1.创建一个新结点newNode
2.将新结点和头结点挂接,newNode.next=head
3.新结点成为头结点,依次往下一个结点遍历,链表插入元素完成,head=newNode
/**
* 头插法
* ListNode head 头结点
* ListNode node 要插入的结点
* int index 要插入的位置
*/
public static ListNode insertListNode(ListNode head,ListNode node,int index){
//判断头结点是否为空
if(head ==null){
//为空,则直接返回要插入的节点(即插入的结点就是头结点)
return node;
}
//获取链表的长度size
int size=getListLength(head);
//判断要插入的位置是否合法
if(index>size+1 ||index<1){
//位置不合法,则直接返回头结点
return head;
}
if(head!=null){
node.next=head;
head=node;
return head;
}
return head;
}
头插法需要注意的是重新将插入的结点作为新的头结点,因为链表是从头结点往后依次遍历。且头插法会改变链表的原有顺序
2.2 链表的尾部位置插入法
将尾结点指向新结点
尾部插入不会改变链表的原有顺序
2.3 链表的中部位置插入
1.先遍历找到插入的位置
2.将插入结点挂载到要插入位置的前一个结点的后继结点上。
3.将插入结点挂载到要插入位置的前一个结点。
完整的链表插入代码
/**
* 链表插⼊
* @param head 链表头节点
* @param node 待插⼊节点
* @param index 待插⼊位置,从1开始
* @return 插⼊后得到的链表头节点
*/
public static ListNode insertNode(ListNode head,ListNode node , int index) {
//判断头结点是否为空
if (head == null) {
//为空,则直接返回要插入的节点(即插入的结点就是头结点)
return node;
}
//获取链表的长度size
int size = getListLength(head);
//判断要插入的位置是否合法
if (index > size+1 || index < 1) {
//位置不合法,则直接返回头结点
return head;
}
// 表头插入
if (index == 1) {
node.next = head;
head = node;
return head;
}
ListNode currentNode = head;
int count = 1;
while (count < index - 1) {
currentNode = currentNode.next;
count++;
}
node.next = currentNode.next;
currentNode.next =node;
return head;
}
node.next = currentNode.next;
currentNode.next =node;
顺序不能颠倒,否则就没有办法找到插入位置的前一个结点的后继结点的位置
总结
以上就是我关于链表学习过程中的认识,希望能够帮助大家更好的认识链表,也欢迎大家留言。