【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

六、单元测试

【Python 单链表详解:从实现到操作全面解析】_第1张图片

七、结语

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

八、送给正在努力的你

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

你可能感兴趣的:(python数据结构,python,开发语言,数据结构,算法,链表)