概念:
链表是一个一个相同节点的 数据元素 组成的一个对象。
对象与对象之间是如何进行联系的?
每一个Object对象有一个 ‘自己‘,用于记录下一个链接的对象。
static class Node {
public int val;
public Node next;
}
链表的增删改查:
遍历链表:
链表只能从头结点往后一次访问,循环结束的点为当前节点为null。
public static int getLength(Node head) {
int length = 0;
Node node = head;
while (node != null) {
length++;
node = node.next;
}
return length;
}
链表插入:
考虑三种情况:
- 头部插入
新节点的下一个只想当前头节点,记住头节点需更新为新节点(记得判断头结点是否为null)
- 中间插入
链表为线性结构,要插入节点必须找到其前一个节点。
插入顺序为:必须先将新节点的 next 和 cur.next先连接,再将cur.next指向新节点。如果将顺序对调,会发现断链,无法找到原先的cur.next节点。
- 尾部插入
和头部一样,只需遍历到最后一个节点,他的下一个节点指向新节点就行
/**
* 链表插入
*
* @param head 链表头节点
* @param nodeInsert 待插入节点
* @param position 待插入位置,取值从2开始
* @return 插入后得到的链表头节点
*/
public static Node insertNode(Node head, Node nodeInsert, int position) {
// 需要判空,否则后面可能会有空指针异常
if (head == null) {
return nodeInsert;
}
//越界判断
int size = getLength(head);
if (position > size + 1 || position < 1) {
System.out.println("位置参数越界");
return head;
}
//在链表开头插入
if (position == 1) {
nodeInsert.next = head;
// return nodeInsert;
head = nodeInsert;
return head;
}
Node pNode = head;
int count = 1;
while (count < position - 1) {
pNode = pNode.next;
count++;
}
nodeInsert.next = pNode.next;
pNode.next = nodeInsert;
return head;
}
链表删除:
删除和添加类似,分为三种情况:头、中、尾
- 删除头部
删除表头元素还是比较简单的,一般只要执行head=head.next就行了。如下图,将head向前移动一次之后,原来的结点不可达,会被JVM回收掉。
- 删除最后一个结点
删除的过程不算复杂,也是找到要删除的结点的前驱结点,这里同样要在提前一个位置判断,例如下图中删除40,其前驱结点为7。遍历的时候需要判断cur.next是否为40,如果是,则只要执行cur.next=null即可,此时结点40变得不可达,最终会被JVM回收掉。
- 删除中间节点
找到前继节点。cur.next = cur.next.next;
/**
* 删除节点
*
* @param head 链表头节点
* @param position 删除节点位置,取值从1开始
* @return 删除后的链表头节点
*/
public static Node deleteNode(Node head, int position) {
if (head == null) {
return null;
}
int size = getLength(head);
if (position > size || position <1) {
System.out.println("输入的参数有误");
return head;
}
if (position == 1) {
//curNode就是链表的新head
return 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;
}
注意点:
我们在赋值Node cur = head时,所有对cur的操作,都是对head的实际操作,因为赋值时是类似于Integer的地址赋值,是直接操作对象的。
连表增加元素和删除元素时,一定要注意顺序,必须考虑到断链的风险,一定要先 ‘保存住’ 下一个对象在操作。反正我们这个新对象是跑不掉的,哈哈哈哈。