一句话总结:
单链表就像一列火车——每节车厢(节点)载着货物(数据),并且只记得下一节车厢的位置,想找特定车厢得从头开始一节节找!
一、单链表结构与功能
- 节点类 (车厢) :存储数据 + 指向下一节点的指针
- 链表类 (火车) :管理头节点 + 实现增删查操作
二、Kotlin 代码实现
// 节点类(车厢)
data class Node<T>(var data: T, var next: Node<T>? = null)
// 单链表类(火车)
class LinkedList<T> {
private var head: Node<T>? = null // 火车头
// 1. 添加节点到头部(新火车头)
fun addToHead(data: T) {
val newNode = Node(data)
newNode.next = head // 新节点指向旧头
head = newNode // 更新头为新节点
}
// 2. 添加节点到尾部(加在最后)
fun addToTail(data: T) {
val newNode = Node(data)
if (head == null) { // 空链表直接设头
head = newNode
return
}
var current = head
while (current?.next != null) { // 找到最后一个节点
current = current.next
}
current?.next = newNode // 挂到尾部
}
// 3. 删除节点(卸下车厢)
fun delete(data: T) {
if (head?.data == data) { // 删除头节点
head = head?.next
return
}
var current = head
while (current?.next != null) {
if (current.next?.data == data) {
current.next = current.next?.next // 跳过目标节点
return
}
current = current.next
}
}
// 4. 检查是否存在(查货物)
fun contains(data: T): Boolean {
var current = head
while (current != null) {
if (current.data == data) return true
current = current.next
}
return false
}
// 5. 打印链表(查看整列火车)
fun printList() {
var current = head
while (current != null) {
print("${current.data} → ")
current = current.next
}
println("null")
}
}
三、测试用例(验车)
fun main() {
val list = LinkedList<String>()
// 测试添加头节点
list.addToHead("香蕉")
list.addToHead("苹果")
list.printList() // 苹果 → 香蕉 → null
// 测试添加尾节点
list.addToTail("西瓜")
list.printList() // 苹果 → 香蕉 → 西瓜 → null
// 测试删除中间节点
list.delete("香蕉")
list.printList() // 苹果 → 西瓜 → null
// 测试删除头节点
list.delete("苹果")
list.printList() // 西瓜 → null
// 测试查找功能
println("是否存在西瓜:${list.contains("西瓜")}") // true
println("是否存在苹果:${list.contains("苹果")}") // false
// 测试空链表操作
list.delete("西瓜")
list.printList() // null
println("是否存在西瓜:${list.contains("西瓜")}") // false
}
四、关键操作图解
初始状态:
head → 苹果 → 香蕉 → 西瓜 → null
删除"香蕉"后:
head → 苹果 → 西瓜 → null
删除"苹果"后:
head → 西瓜 → null
五、时间复杂度
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| 插入到头部 | O(1) | 直接修改头节点 |
| 插入到尾部 | O(n) | 需要遍历到末尾 |
| 删除/查找 | O(n) | 最坏情况遍历整个链表 |
口诀:
链表就像小火车,
增删头尾要掌握。
查询只能从头找,
实用场景要选好!