何为链表?
链表由很多个节点组成,每个节点包括该节点的数据以及指向列表下一个节点的地址。 其中链表的内存中不一定是连续集中存储的。 单个节点结构:
Java如何构造链表
完成下面的链表,也就是通过栈中的地址找到val(1)的值,再通过val(1)节点中存放的val(2)的地址找到val(2)的值,依次类推。
java
package lukasy.chapter1_linklist.level1;
import org.w3c.dom.Node;
public class BasicLink {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6};
Node head = initLinkedList(a);
System.out.println(head);
}
private static Node initLinkedList(int[] array) {
Node head = null, cur = null;
for (int i = 0; i < array.length; i++) {
Node newNode = new Node(array[i]);
newNode.next = null;
if (i == 0) {
head = newNode;
cur = newNode;
} else {
cur.next = newNode;
cur = newNode;
}
}
return head;
}
static class Node {
public int val;
public Node next;
public Node(int x) {
val = x;
next = null;
}
}
}
java
package lukasy.chapter1_linklist.level1;
public class ListNode {
public int val;
public ListNode next;
public ListNode(int x) {
val = x;
next = null;
}
}
链表的CRUD
在单链表中,任何操作都将链表从头到尾逐个访问 ,所以一定要找到表头的位置
java
public static int getListLength(Node head) {
int length = 0;
Node node = head;
while (node != null) {
length++;
node = node.next;
}
return length;
}
链表的插入
- 在表头插入新的节点
首先要创建一个新的节点,让新的节点的指针域指向原先的head节点,再将head指向新的节点。
- 在表中间插入新的节点
首先要确定插入节点位置位于哪两个节点之间(也就是新节点的前驱和后继),然后将新节点的指针域指向前驱节点的指针域(也就是新节点指针域指向后继节点),之后让前驱节点的指针域指向新节点 。这两步顺序不能错,是以为如果直接让前驱节点的指针域指向新的节点,那么前驱节点原本的指针域就会丢失,也就是说新的节点的指针域将不会指向下一个后继节点。 3. 在表尾插入新的节点
只需要将表尾节点的指针域指向新的节点即可。
java
/**
* 链表插入
*
* @param head 链表头节点
* @param nodeInsert 待插入节点
* @param position 待插入位置,从1开始
* @return 插入后得到的链表头节点
*/
public static Node insertNode(Node head, Node nodeInsert, int position) {
if (head == null) {
//待插入节点为表头的节点
return nodeInsert;
}
//检查判断存放元素个数
int size = getListLength(head);
if (position > size + 1 || position < 1) {
System.out.println("位置参数越界");
return head;
}
//表头插入
if (position == 1) {
nodeInsert.next = head;
head = nodeInsert;
return head;
}
//创建一个节点获取头节点来遍历链表
Node pNode = head;
//创建一个count来统计pNode移动的位置
int count = 1;
while (count < position - 1) {
pNode = pNode.next;
count++;
}
nodeInsert.next = pNode.next;
pNode.next = nodeInsert;
return head;
}
链表的删除
- 删除表头的节点
直接将head指向下一个next节点即可,JVM会回收原来的头节点。
- 删除表尾的节点
遍历表尾节点的前一个节点,判断该节点的指针域是否指向的是尾节点,如果是的话直接将该节点指针域指向null,同样地,JVM会回收原来的尾节点。
- 删除表中的节点
找到要删除的节点,将该节点前驱节点的指针域指向该节点的后继节点 即可,同样地,JVM会回收该节点。
java
/**
* 删除节点
*
* @param head 头节点
* @param position 删除节点位置,取值从1开始
* @return 删除后的链表头节点
*/
public static Node deleteNode(Node head, int position) {
if (head == null) {
return head;
}
int size = getListLength(head);
if (position > size || position < 1) {
System.out.print("输入参数有误");
return head;
}
if (position == 1) {
head = head.next;
} else {
Node cur = head;
int count = 1;
while (count < position - 1) {
cur = cur.next;
count++;
}
cur.next = cur.next.next;
}
return head;
}