提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
— 链表基础整理
一、链表基础概念
链表的基本结构类似于铁链
由一个又一个的节点-在Java中即为一个又一个的对象引用,相互嵌套形成。
根据这一特点,可以定义出链表的对象模型:
@Data
public class Node {
/** 节点包含的数据值 */
private int data;
/** 指向下个节点的对应引用 */
private Node next;
public Node(int data) {
this.data = data;
// 这一行本质上没什么用,写出来只是为了看的更清晰
this.next = null;
}
}
二、链表增加元素,首部,中部,尾部分别会有什么问题
链表插入元素逻辑如下:
/**
* 链表插入
*
* @param head
* 头节点
* @param nodeInsert
* 插入节点
* @param position
* 插入位置 从1开始;
* @return 新的头节点
*/
private static Node insertLinkedList(Node head, Node nodeInsert, int position) {
if (head == null) {
// 头节点不存在,插入节点直接成为头节点,并且没有后续节点指向
head = nodeInsert;
}
// 判断插入位置是否越界
int size = getLinkedListLength(head);
if (position > size + 1 || position < 1) {
System.out.println("插入位置越界");
return head;
}
// 在头节点插入
if (position == 1) {
//插入节点为新的头节点,插入节点的后续节点指向原来的头节点
nodeInsert.next = head;
// 这里可以直接返回nodeInsert,也可以把nodeInsert的引用重新赋值给head,从字面意思上更好理解,head依然是头节点
head = nodeInsert;
return head;
}
// 中部插入(包含尾部插入):原理是获取到要插入位置的前一个节点A,然后通过将插入节点连接到节点A之后,并且将插入节点的后续节点指向原来的节点A的后续节点,以此实现链表插入
Node cur = head;
int count = 1;
while (count < position - 1) {
// 从头节点开始遍历,直到获取到节点A
cur = cur.next;
count++;
}
// 将插入节点的后续节点指向节点A已有的后续节点
nodeInsert.next = cur.next;
// 修改节点A的后续节点为插入节点
cur.next = nodeInsert;
return head;
}
1.头部插入的问题
在头部插入需要注意插入后原来的头节点已经不再是头节点,而是新插入的节点成为头节点。
当然,从上述代码上看,头节点依然是head,但实际上这个head指向的内存地址已经更改成插入节点的内存地址
2.中部/尾部插入的问题
在中部/尾部插入的时候需要注意节点丢失。
首先要先找到插入节点应该在的位置,然后获取到前一个节点信息。注意这里不能获取后一个节点,如果拿到的是后一个节点信息的话,再后续交换指向节点的时候就会丢失原节点的信息。
例如,原链表数据:1,2,3,4,5,6;
现在要在position = 3的位置上插入一个新的节点:2.5;链表从1开始计算
这种情况下,我们需要获取的是Node(2)的信息,根据Node(2)的节点信息,将插入节点进行关联。
三、链表删除元素,首部,中部,尾部分别会有什么问题
链表删除元素逻辑:
private static Node removeLinkedList(Node head, int position) {
if (head == null) {
return null;
}
int size = getLinkedListLength(head);
if (position > size || position < 1) {
System.out.println("要移除的位置越界");
return head;
}
if (position == 1) {
// 头节点移除,只需要将head的引用调整成head原先的后续节点即可
head = head.next;
} else {
Node cur = head;
int count = 1;
while (count < position - 1) {
cur = cur.next;
count++;
}
Node curNode = cur.next;
cur.next = curNode.next;
}
return head;
}
删除节点需要注意的地方和新增节点一致
双向链表构造以及新增删除逻辑
todo