Java各种操作单链表
单链表是一种常用的数据结构,在大学数据结构课程中也学习过,此文章记录一些单链表的简单操作
创建单链表
根据自定义长度创建单链表:
// 创建单链表
public Node createNodeLink(int N) {
// 定义一个临时节点
Node preNode = new Node(-1);
Node head = new Node(1);
preNode.next = head;
for (int i = 1; i < N; i++) {
head.next = new Node(i + 1);
head = head.next;
}
return preNode.next;
}
统计单链表长度
// 计算链表长度
public int getNodesLength(Node head) {
int len = 0;
Node tmpNode = head;
while (tmpNode != null) {
len++;
tmpNode = tmpNode.next;
}
return len;
}
求单链表倒数第K个节点数据
// 获取链表的倒数第K个节点
public Node getLastKNode(Node head, int K) {
int len = getNodesLength(head);
if (K > len) {
throw new IllegalArgumentException("参数非法,长度太大");
}
Node firstNode = head;
Node secondNode = head;
while (K > 0) {
firstNode = firstNode.next;
K--;
}
while (firstNode != null) {
firstNode = firstNode.next;
secondNode = secondNode.next;
}
return secondNode;
}
链表的反转
// 翻转链表
public Node reverseNode(Node head) {
Node preNode = null;
// 链表翻转核心
while (head != null) {
/**
* 创建之后的链表信息为:1->2->3->4...
*/
// 创建临时节点,第一步将临时节点 tempNode = 2这个节点
Node tempNode = head.next;
// 将当前头结点head = 1的下一个节点指向preNode = null
head.next = preNode;
// 将preNode节点设置为头结点head = 1
preNode = head;
// 将最新的head节点设置成为node = 2这个节点;至此第一个节点head = 1就实现了翻转
head = tempNode;
}
return preNode;
}
不知道head头结点,删除任意中间节点
// 不知道头结点是可以删除任意节点,但是除链表的tail尾结点
public Node removeAnyNode(Node node){
// 将需要删除的当前节点的后面一个节点向前移一位,用后面一个节点覆盖当前节点数据,同时链接断开,实现删除当前节点
// 定义临时节点赋值为下一个节点数据
Node tempNode = node.next;
// 将当前节点的数据值val变成下一个几点
node.val = tempNode.val;
// 当前节点的下一个节点直接指向下下个节点
node.next = tempNode.next;
return node;
}
完整代码
import org.junit.jupiter.api.Test;
public class NodeLink {
public class Node {
int val;
Node next;
public Node(int val) {
this.val = val;
}
}
// 创建单链表
public Node createNodeLink(int N) {
// 定义一个临时节点
Node preNode = new Node(-1);
Node head = new Node(1);
preNode.next = head;
for (int i = 1; i < N; i++) {
head.next = new Node(i + 1);
head = head.next;
}
return preNode.next;
}
// 翻转链表
public Node reverseNode(Node head) {
Node preNode = null;
// TODO 链表翻转核心
while (head != null) {
/**
* 创建之后的链表信息为:1->2->3->4...
*/
// 创建临时节点,第一步将临时节点 tempNode = 2这个节点
Node tempNode = head.next;
// 将当前头结点head = 1的下一个节点指向preNode = null
head.next = preNode;
// 将preNode节点设置为头结点head = 1
preNode = head;
// 将最新的head节点设置成为node = 2这个节点;至此第一个节点head = 1就实现了翻转
head = tempNode;
}
return preNode;
}
// 计算链表长度
public int getNodesLength(Node head) {
int len = 0;
Node tmpNode = head;
while (tmpNode != null) {
len++;
tmpNode = tmpNode.next;
}
return len;
}
// 获取链表的倒数第K个节点
public Node getLastKNode(Node head, int K) {
int len = getNodesLength(head);
if (K > len) {
throw new IllegalArgumentException("参数非法,长度太大");
}
Node firstNode = head;
Node secondNode = head;
while (K > 0) {
firstNode = firstNode.next;
K--;
}
while (firstNode != null) {
firstNode = firstNode.next;
secondNode = secondNode.next;
}
return secondNode;
}
// 打印翻转之后的链表
@Test
public void printReverseNode() {
Node head = createNodeLink(15);
Node newHead = reverseNode(head);
System.out.println("翻转之后的链表:");
while (newHead != null) {
if (newHead.next != null) {
System.out.print(newHead.val + "->");
} else {
System.out.print(newHead.val);
}
newHead = newHead.next;
}
}
// 打印原始创建的链表数据
@Test
public void printRawNode() {
Node head = createNodeLink(20);
System.out.println("链表长度len="+getNodesLength(head));
System.out.println("获取倒数第5的节点:"+getLastKNode(head,5).val);
System.out.println("创建初始链表:");
while (head != null) {
String linkChar = head.next != null ? "->" : "";
System.out.print(head.val + linkChar);
head = head.next;
}
}
}