基础结构

// 链表节点内部类
static class Node {
String data; // 节点存储的数据(使用String类型,与Python示例一致)
Node next; // 指向下一个节点的引用
// 节点构造方法
public Node(String data) {
this.data = data;
this.next = null;
}
}
private Node head; // 链表头节点
// 单链表构造方法
public SinglyLinkedList() {
this.head = null;
}
插入
单链表的插入操作有三种情况:头部插入、中间插入和尾部插入
头部插入
将新节点的next指向当前的头节点,然后将头节点更新为新节点。

算法步骤:
1. 创建新节点
2. 将新节点的next指向当前的头节点
3. 更新头节点为新节点
/**
* 头部添加节点(头插法)
* @param data 插入的数据
*/
public void prepend(String data) {
Node newNode = new Node(data);
// 将新节点的next指向当前的头节点
newNode.next = head;
// 更新头节点为新节点
head = newNode;
}
尾部插入
遍历链表找到最后一个节点,然后将最后一个节点的next指向新节点。

算法步骤:
1. 创建新节点
2. 如果链表为空,将新节点设为头节点
3. 否则,遍历到链表末尾
4. 将最后一个节点的next指向新节点
/**
* 尾部添加节点(尾插法)
* @param data 插入的数据
*/
public void append(String data) {
Node newNode = new Node(data);
// 如果链表为空,将新节点设为头节点
if (head == null) {
head = newNode;
return;
}
// 遍历到链表末尾
Node current = head;
while (current.next != null) {
current = current.next;
}
// 将新节点链接到末尾
current.next = newNode;
}
指定位置插入
将新节点的next指向目标节点的next,然后将目标节点的next指向新节点。

算法步骤:
1. 创建新节点
2. 将新节点的next指向目标节点的next
3. 将目标节点的next指向新节点
/**
* 在指定节点后添加新节点
* @param prevNode 指定的前一个节点
* @param data 插入的数据
*/
public void insertAfterNode(Node prevNode, String data) {
// 检查前一个节点是否存在
if (prevNode == null) {
System.out.println("前一个节点不存在");
return;
}
Node newNode = new Node(data);
// 将新节点的next指向前一个节点的next
newNode.next = prevNode.next;
// 将前一个节点的next指向新节点
prevNode.next = newNode;
}
删除
查找要删除的节点,并将其前一个节点的next指向要删除节点的next。

算法步骤:
1. 如果头节点是要删除的节点,直接将头节点更新为下一个节点
2. 否则,遍历链表找到要删除的节点及其前一个节点
3. 将前一个节点的next指向要删除节点的next
4. 释放要删除的节点
/**
* 删除包含特定值的节点
* @param key 要删除的节点值
*/
public void deleteNode(String key) {
// 保存当前节点
Node current = head;
// 如果头节点包含要删除的值
if (current != null && current.data.equals(key)) {
head = current.next;
current = null;
return;
}
// 搜索要删除的节点
Node prev = null;
while (current != null && !current.data.equals(key)) {
prev = current;
current = current.next;
}
// 如果没有找到要删除的节点
if (current == null) {
return;
}
// 将前一个节点的next跳过当前节点指向下一个节点
prev.next = current.next;
current = null;
}
/**
* 按位置删除节点
* @param position 要删除的节点位置(从0开始)
*/
public void deleteAtPos(int position) {
if (head == null) {
return;
}
// 如果删除头节点
if (position == 0) {
head = head.next;
return;
}
Node current = head;
for (int i = 0; i < position - 1; i++) {
if (current == null || current.next == null) {
return;
}
current = current.next;
}
// 如果到达链表末尾
if (current == null || current.next == null) {
return;
}
// 删除current.next节点
Node nextNode = current.next.next;
current.next = nextNode;
}
查找
遍历链表查找特定值的节点。

算法步骤:
1. 从头节点开始遍历链表
2. 检查每个节点的数据是否等于目标值
3. 如果找到,返回True
4. 如果遍历完整个链表都没找到,返回False
/**
* 查找包含特定值的节点
* @param key 要查找的值
* @return 是否找到
*/
public boolean search(String key) {
Node current = head;
while (current != null) {
if (current.data.equals(key)) {
return true;
}
current = current.next;
}
return false;
}
更新
查找特定值的节点并更新其数据。

算法步骤:
1. 从头节点开始遍历链表
2. 检查每个节点的数据是否等于目标值
3. 如果找到,更新节点数据并返回True
4. 如果遍历完整个链表都没找到,返回False
/**
* 更新节点值
* @param key 要更新的旧值
* @param newData 新值
* @return 是否更新成功
*/
public boolean updateNode(String key, String newData) {
Node current = head;
while (current != null) {
if (current.data.equals(key)) {
current.data = newData;
return true;
}
current = current.next;
}
return false;
}
遍历
从头节点开始遍历链表
/**
* 打印链表
*/
public void printList() {
Node current = head;
while (current != null) {
System.out.print(current.data + " -> ");
current = current.next;
}
System.out.println("null");
}
完整代码
/**
* @Author Stringzhua
* @Date 2025/10/23 14:51
* description:
*/
public class SinglyLinkedList {
// 链表节点内部类
static class Node {
String data; // 节点存储的数据(使用String类型,与Python示例一致)
Node next; // 指向下一个节点的引用
// 节点构造方法
public Node(String data) {
this.data = data;
this.next = null;
}
}
private Node head; // 链表头节点
// 单链表构造方法
public SinglyLinkedList() {
this.head = null;
}
/**
* 尾部添加节点(尾插法)
* @param data 插入的数据
*/
public void append(String data) {
Node newNode = new Node(data);
// 如果链表为空,将新节点设为头节点
if (head == null) {
head = newNode;
return;
}
// 遍历到链表末尾
Node current = head;
while (current.next != null) {
current = current.next;
}
// 将新节点链接到末尾
current.next = newNode;
}
/**
* 头部添加节点(头插法)
* @param data 插入的数据
*/
public void prepend(String data) {
Node newNode = new Node(data);
// 将新节点的next指向当前的头节点
newNode.next = head;
// 更新头节点为新节点
head = newNode;
}
/**
* 在指定节点后添加新节点
* @param prevNode 指定的前一个节点
* @param data 插入的数据
*/
public void insertAfterNode(Node prevNode, String data) {
// 检查前一个节点是否存在
if (prevNode == null) {
System.out.println("前一个节点不存在");
return;
}
Node newNode = new Node(data);
// 将新节点的next指向前一个节点的next
newNode.next = prevNode.next;
// 将前一个节点的next指向新节点
prevNode.next = newNode;
}
/**
* 删除包含特定值的节点
* @param key 要删除的节点值
*/
public void deleteNode(String key) {
// 保存当前节点
Node current = head;
// 如果头节点包含要删除的值
if (current != null && current.data.equals(key)) {
head = current.next;
current = null;
return;
}
// 搜索要删除的节点
Node prev = null;
while (current != null && !current.data.equals(key)) {
prev = current;
current = current.next;
}
// 如果没有找到要删除的节点
if (current == null) {
return;
}
// 将前一个节点的next跳过当前节点指向下一个节点
prev.next = current.next;
current = null;
}
/**
* 按位置删除节点
* @param position 要删除的节点位置(从0开始)
*/
public void deleteAtPos(int position) {
if (head == null) {
return;
}
// 如果删除头节点
if (position == 0) {
head = head.next;
return;
}
Node current = head;
for (int i = 0; i < position - 1; i++) {
if (current == null || current.next == null) {
return;
}
current = current.next;
}
// 如果到达链表末尾
if (current == null || current.next == null) {
return;
}
// 删除current.next节点
Node nextNode = current.next.next;
current.next = nextNode;
}
/**
* 查找包含特定值的节点
* @param key 要查找的值
* @return 是否找到
*/
public boolean search(String key) {
Node current = head;
while (current != null) {
if (current.data.equals(key)) {
return true;
}
current = current.next;
}
return false;
}
/**
* 更新节点值
* @param key 要更新的旧值
* @param newData 新值
* @return 是否更新成功
*/
public boolean updateNode(String key, String newData) {
Node current = head;
while (current != null) {
if (current.data.equals(key)) {
current.data = newData;
return true;
}
current = current.next;
}
return false;
}
/**
* 打印链表
*/
public void printList() {
Node current = head;
while (current != null) {
System.out.print(current.data + " -> ");
current = current.next;
}
System.out.println("null");
}
public static void main(String[] args) {
// 创建一个空链表
SinglyLinkedList linkedList = new SinglyLinkedList();
// 在末尾添加节点
linkedList.append("A");
linkedList.append("B");
linkedList.append("C");
System.out.println("原始链表:");
linkedList.printList(); // 输出: A -> B -> C -> null
// 在头部添加节点
linkedList.prepend("X");
System.out.println("在头部添加 'X' 后:");
linkedList.printList(); // 输出: X -> A -> B -> C -> null
// 在 'A' 后添加节点
Node current = linkedList.head.next; // 'A' 节点
linkedList.insertAfterNode(current, "Y");
System.out.println("在 'A' 后添加 'Y' 后:");
linkedList.printList(); // 输出: X -> A -> Y -> B -> C -> null
// 删除值为 'B' 的节点
linkedList.deleteNode("B");
System.out.println("删除值为 'B' 的节点后:");
linkedList.printList(); // 输出: X -> A -> Y -> C -> null
// 查找值为 'Y' 的节点
System.out.println("查找值为 'Y' 的节点: " + linkedList.search("Y")); // 输出: true
System.out.println("查找值为 'B' 的节点: " + linkedList.search("B")); // 输出: false
// 更新值为 'Y' 的节点为 'Z'
linkedList.updateNode("Y", "Z");
System.out.println("更新值为 'Y' 的节点为 'Z' 后:");
linkedList.printList(); // 输出: X -> A -> Z -> C -> null
}
}
时间空间复杂度分析
| 操作 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 访问元素(按索引) | O(n) | O(1) | 不支持随机访问,必须从头节点开始遍历直到找到第n个元素 |
| 访问元素(头部) | O(1) | O(1) | 可以直接通过头指针访问头部元素 |
| 访问元素(尾部) | O(n) | O(1) | 如果没有尾指针,则需遍历整个链表;有尾指针则为O(1) |
| 插入元素(头部) | O(1) | O(1) | 只需调整头指针和新节点的指针 |
| 插入元素(尾部) | O(n) | O(1) | 没有尾指针时需要遍历到尾部;有尾指针则为O(1) |
| 插入元素(中间) | O(n) | O(1) | 需要先找到插入位置(O(n)),然后调整指针(O(1)) |
| 删除元素(头部) | O(1) | O(1) | 只需调整头指针让它指向第二个节点 |
| 删除元素(尾部) | O(n) | O(1) | 需要遍历到倒数第二个节点将其next指针置空 |
| 删除元素(中间) | O(n) | O(1) | 需要找到目标节点的前一个节点(O(n)),然后调整指针(O(1)) |
| 查找元素 | O(n) | O(1) | 最坏情况下需要遍历整个链表 |
| 更新元素 | O(n) | O(1) | 先查找(O(n))再更新(O(1)) |
| 遍历 | O(n) | O(1) | 从头到尾访问每个节点一次 |
926

被折叠的 条评论
为什么被折叠?



