Python单链表全方位解析:从实现细节到操作技巧的深入解读

文章目录

  • 概要
  • 一、节点类 Node 的设计
  • 二、单链表类 SingleLinkList 的定义
  • 三、常用操作详解
  • 1. 判断链表是否为空:is_empty()
  • 2. 获取链表长度:get_length()
  • 3. 获取指定位置的元素:get(pos)
  • 4. 查找元素首次出现的位置:get_first_index(item)
  • 5. 头插法:insert_head(item)
  • 6. 尾插法:insert_tail(item)
  • 7. 指定位置插入:insert(pos, item)
  • 8. 删除指定位置的节点:remove(pos)
  • 9. 遍历打印链表:travel()
  • 四、关键知识点总结
  • 五、完整测试示例
  • 六、单元测试
  • 七、结语
  • 八、送给正在努力的你
  • 概要

    在数据结构中,链表是一种非常基础且重要的线性结构。与数组不同,链表通过节点之间的引用(指针)来组织数据,具有动态内存分配、插入和删除效率高等优点。
    本文将围绕一个完整的单链表(Singly Linked List) 实现进行讲解,并详细说明每个方法的逻辑与作用,帮助你从零构建对链表的理解。

    一、节点类 Node 的设计

    class Node:
        def __init__(self, item=None, next=None):
            self.item = item
            self.next = next
    

    功能说明:

  • item:用于存储当前节点的数据内容,可以是任意类型(整数、字符串、对象等)
  • next:指向下一个节点的引用,默认为 None,表示链表结束
  • 二、单链表类 SingleLinkList 的定义

    class SingleLinkList:
        def __init__(self):
            self.__head = Node()  # 初始化头节点
    

    功能说明:

  • 使用虚拟头节点 __head 简化插入和删除操作
  • 虚拟头节点不存储有效数据,仅作为起始点
  • 三、常用操作详解

    1. 判断链表是否为空:is_empty()

    def is_empty(self):
        return self.__head.next is None
    

    功能说明:

  • 如果虚拟头节点的 next 为 None,说明链表中没有实际数据节点
  • 时间复杂度:O(1)
  • 2. 获取链表长度:get_length()

    def get_length(self):
        length = 0
        p = self.__head.next
        while p is not None:
            p = p.next
            length += 1
        return length
    

    功能说明:

  • 遍历整个链表,统计有效节点数量
  • 时间复杂度:O(n)
  • 3. 获取指定位置的元素:get(pos)

    def get(self, pos):
        if pos < 0:
            raise IndexError("Index out of range")
        p = self.__head.next
        index = 0
        while index < pos and p is not None:
            p = p.next
            index += 1
        if p is None:
            raise IndexError(f"Index {pos} out of range")
        return p.item
    

    功能说明:

  • 从第一个有效节点开始遍历,直到找到目标索引或越界
  • 支持负数下标检查
  • 时间复杂度:O(n)
  • 示例:

    sll = SingleLinkList()
    sll.insert_head(10)
    sll.insert_head(20)
    sll.insert_head(30)
    
    print(sll.get(0))  # 输出 30
    print(sll.get(2))  # 输出 10
    

    4. 查找元素首次出现的位置:get_first_index(item)

    def get_first_index(self, item):
        p = self.__head.next
        index = 0
        while p is not None and not (p.item == item):
            p = p.next
            index += 1
        if p is not None:
            return index
        else:
            return -1
    

    功能说明:

  • 遍历链表查找值为 item 的节点,返回其索引
  • 若未找到则返回 -1
  • 时间复杂度:O(n)
  • 示例:

    sll = SingleLinkList()
    sll.insert_head(10)
    sll.insert_head(20)
    sll.insert_head(30)

    print(sll.get_first_index(20)) # 输出 1
    print(sll.get_first_index(50)) # 输出 -1

    5. 头插法:insert_head(item)

    def insert_head(self, item):
        p = self.__head
        new_node = Node(item)
        new_node.next = p.next
        p.next = new_node
    

    功能说明:

  • 在链表头部插入新节点
  • 插入后原头节点成为第二个节点
  • 时间复杂度:O(1)
  • 示例:

    sll.insert_head(10)
    sll.insert_head(20)
    sll.travel()  # 输出: 20 10
    

    6. 尾插法:insert_tail(item)

    def insert_tail(self, item):
        p = self.__head
        new_node = Node(item)
        while p.next is not None:
            p = p.next
        p.next = new_node
    

    功能说明:

  • 遍历到链表末尾,将新节点添加到最后一个节点之后
  • 时间复杂度:O(n)
  • 示例:

    sll.insert_tail(30)
    sll.insert_tail(40)
    sll.travel() # 输出: 30 40

    7. 指定位置插入:insert(pos, item)

    def insert(self, pos, item):
        if pos < 0:
            self.insert_head(item)
            return
        p = self.__head
        index = 0
        while p is not None and index < pos:
            p = p.next
            index += 1
        if p is None:
            self.insert_tail(item)
        else:
            new_node = Node(item)
            new_node.next = p.next
            p.next = new_node
    

    功能说明:

  • 插入到指定位置(支持头插、尾插、中间插入)
  • 如果 pos <= 0,默认执行头插
  • 如果 pos >= length,自动执行尾插
  • 时间复杂度:O(n)
  • 示例:

    sll.insert(2, 25)  # 插入到第三个位置
    sll.travel()  # 输出: 20 10 25 30 40
    

    8. 删除指定位置的节点:remove(pos)

    def remove(self, pos):
        if pos < 0:
            raise IndexError("Index out of range")
        p = self.__head
        index = 0
        while p is not None and index < pos:
            p = p.next
            index += 1
        if p is None:
            raise Exception("Index out of range")
        p.next = p.next.next
    

    功能说明:

  • 找到要删除节点的前一个节点,修改其 next 指针跳过目标节点
  • 时间复杂度:O(n)
  • 示例:

    sll.remove(2)  # 删除第3个节点(即25)
    sll.travel()  # 输出: 20 10 30 40
    

    9. 遍历打印链表:travel()

    def travel(self):
        p = self.__head.next
        while p is not None:
            print(p.item, end=' ')
            p = p.next
        print()
    

    功能说明:

  • 从第一个有效节点开始,依次访问所有节点并打印数据
  • 时间复杂度:O(n)
  • 四、关键知识点总结

    操作 方法名 时间复杂度 说明
    判空 is_empty() O(1) 检查是否有数据节点
    获取长度 get_length() O(n) 遍历链表计数
    获取元素 get(pos) O(n) 定位并返回对应节点数据
    查找索引 get_first_index(item) O(n) 返回首次出现的位置
    头部插入 insert_head(item) O(1) 插入到第一个节点
    尾部插入 insert_tail(item) O(n) 需要遍历到末尾
    中间插入 insert(pos, item) O(n) 定位后插入
    删除节点 remove(pos) O(n) 定位后跳过目标节点
    遍历输出 travel() O(n) 逐个打印

    五、完整测试示例

    sll = SingleLinkList()
    
    sll.insert_head(10)
    sll.insert_head(20)
    sll.insert_head(30)
    sll.insert_head(40)
    sll.insert_head(50)
    
    print("初始链表:")
    sll.travel()  # 输出: 50 40 30 20 10
    
    sll.insert(3, 250)
    print("插入 250 到位置 3:")
    sll.travel()  # 输出: 50 40 30 250 20 10
    
    sll.remove(3)
    print("删除位置 3 的节点:")
    sll.travel()  # 输出: 50 40 30 20 10
    
    print("查找 20 的位置:", sll.get_first_index(20))  # 输出: 3
    print("获取位置 2 的元素:", sll.get(2))  # 输出: 30
    

    六、单元测试

    单元测试通过

    七、结语

    单链表作为一种基础的数据结构,虽然在随机访问上不如数组高效,但在频繁插入和删除场景下具有明显优势。掌握链表的插入、删除、查找、遍历等基本操作,是学习更复杂数据结构(如栈、队列、图、树)的基础。

    八、送给正在努力的你

    学习数据结构和算法的过程就像在黑暗中摸索前行,一开始你可能看不清方向,也看不到终点。但请相信,每一步看似笨拙的尝试,其实都在悄悄为你打下基础。那些你花时间理解的每一行代码,每一个你修复的 bug,每一次你重新思考逻辑的过程,都会成为你未来面对更复杂问题时的底气。你不需要一开始就写出完美的代码,只要你在不断尝试、不断改进,就已经走在了成为优秀开发者的路上。愿你始终保有信心,在编程的路上越走越稳,越走越远。你不是不行,只是还在成长。

    作者:高速排骨

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python单链表全方位解析:从实现细节到操作技巧的深入解读

    发表回复