一句话说透数据结构里面的实现一个简单的单链表

120 阅读2分钟

一句话总结:
单链表就像一列火车——每节车厢(节点)载着货物(数据),并且只记得下一节车厢的位置,想找特定车厢得从头开始一节节找!


一、单链表结构与功能

  • 节点类 (车厢) :存储数据 + 指向下一节点的指针
  • 链表类 (火车) :管理头节点 + 实现增删查操作

二、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)最坏情况遍历整个链表

口诀:
链表就像小火车,
增删头尾要掌握。
查询只能从头找,
实用场景要选好!