Python - 链表浅析

Python - 链表浅析

本篇用Python代码模拟链表

1. 链表介绍

概述

链表属于数据结构之 线性结构 的一种,每个节点都只能有 1个前驱1个后继 节点。

作用

  • 用于优化顺序表的弊端(如果没有足够的连续的内存空间,会导致扩容失败)。
  • 链表扩容时,有地儿就行,连不连续无所谓。

组成

节点 组成,其中节点由以下两部分组成:

  • 元素域 (数值域):存储数据。
  • 链接域 (地址域):存储下一个节点的地址。

分类

根据节点类型不同,链表主要分为:

  • 单向链表 :节点由1个数值域和1个地址域组成,前边节点的地址域存储的是后续节点的地址,最后1个节点的地址域为 None
  • 单向循环链表:尾节点的地址域指向头节点。
  • 双向链表:节点包含前驱指针和后继指针。
  • 双向循环链表 :双向链表的头尾相连。

2. 自定义代码模拟链表 - 思路分析

  1. NodeObj 类 (节点类)

    • item: 数值域 (元素域)
    • next: 地址域 (链接域)
  2. LinkedList 类 (链表类)

    • 属性 :
      • head: 表示头结点,指向第1个节点。
    • 行为 (方法) :
      • is_empty(): 判断链表是否为空
      • length(): 获取链表长度
      • travel(): 遍历整个链表
      • add(item): 链表头部添加元素
      • append(item): 链表尾部添加元素
      • insert(pos, item): 指定位置添加元素
      • remove(item): 删除节点
      • search(item): 查找节点是否存在
  3. 测试 : 在 main 模块中进行功能验证。


3. 代码实现

python 复制代码
# 1. 自定义 NodeObj 类,表示节点类
class NodeObj:
    # 初始化属性
    def __init__(self, item):
        self.item = item        # 元素域 (数值域)
        self.next = None        # 链接域 (地址域)


# 2. 自定义 LinkedList 类,表示链表
class LinkedList:
    # 1. 初始化属性
    def __init__(self, node=None):
        self.head = node      # 链表的头结点,指向第1个节点

    # 2. is_empty(self) 链表是否为空
    def is_empty(self):
        return self.head is None

    # 3. length(self) 链表长度
    def length(self):
        count = 0
        cur = self.head
        while cur is not None:
            count += 1
            cur = cur.next
        return count

    # 4. travel(self) 遍历整个链表
    def travel(self):
        cur = self.head
        items = []
        while cur is not None:
            items.append(str(cur.item))
            cur = cur.next
        print(" -> ".join(items))

    # 5. add(self, item) 链表头部添加元素
    def add(self, item):
        """头部插入,时间复杂度 O(1)"""
        node = NodeObj(item)
        node.next = self.head
        self.head = node

    # 6. append(self, item) 链表尾部添加元素
    def append(self, item):
        """尾部追加,时间复杂度 O(n)"""
        node = NodeObj(item)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next is not None:
                cur = cur.next
            cur.next = node

    # 7. insert(self, pos, item) 指定位置添加元素
    def insert(self, pos, item):
        """
        :param pos: 从0开始索引
        :param item: 插入的数据
        """
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = NodeObj(item)
            count = 0
            pre = self.head
            # 移动到 pos 位置的前一个节点
            while count < (pos - 1):
                count += 1
                pre = pre.next
            # 执行插入
            node.next = pre.next
            pre.next = node

    # 8. remove(self, item) 删除节点
    def remove(self, item):
        cur = self.head
        pre = None
        while cur is not None:
            if cur.item == item:
                # 判断是否是头结点
                if pre is None:
                    self.head = cur.next
                else:
                    pre.next = cur.next
                return True # 删除成功
            else:
                pre = cur
                cur = cur.next
        return False # 未找到

    # 9. search(self, item) 查找节点是否存在
    def search(self, item):
        cur = self.head
        while cur is not None:
            if cur.item == item:
                return True
            cur = cur.next
        return False


# 3. 在 main 中测试
if __name__ == '__main__':
    print("--- 测试节点类 ---")
    # 3.1 测试节点类
    node1 = NodeObj(10)

    # 3.2 打印当前节点的 元素域 (数值域) 和 链接域 (地址域)
    print(f'元素域 (数值域): {node1.item}')    # 10
    print(f'链接域 (地址域): {node1.next}')    # None
    print(f'node1 对象: {node1}')            # 地址值
    print(f'node1 的类型: {type(node1)}')
    print('-' * 20)

    print("\n--- 测试链表类 ---")
    # 3.2 测试链表类
    my_linkedlist = LinkedList(node1)
    print(f'头结点为:{my_linkedlist.head}')
    print(f'头结点的元素域:{my_linkedlist.head.item}')    # 10
    print(f'头结点的地址域:{my_linkedlist.head.next}')    # None
    
    print("\n--- 功能测试 ---")
    # 测试是否为空
    print(f"链表是否为空:{my_linkedlist.is_empty()}")
    print(f"链表长度:{my_linkedlist.length()}")
    
    # 遍历
    print("当前链表内容:", end="")
    my_linkedlist.travel()
    
    # 头部添加
    my_linkedlist.add(20)
    print("头部添加 20 后:", end="")
    my_linkedlist.travel()
    
    # 尾部添加
    my_linkedlist.append(30)
    print("尾部添加 30 后:", end="")
    my_linkedlist.travel()
    
    # 指定位置插入
    my_linkedlist.insert(1, 25)
    print("位置 1 插入 25 后:", end="")
    my_linkedlist.travel()
    
    # 查找
    print(f"查找 25 是否存在:{my_linkedlist.search(25)}")
    print(f"查找 100 是否存在:{my_linkedlist.search(100)}")
    
    # 删除
    my_linkedlist.remove(25)
    print("删除 25 后:", end="")
    my_linkedlist.travel()
    
    print(f"最终链表长度:{my_linkedlist.length()}")
相关推荐
m0_733612211 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
大连好光景2 小时前
conda管理包还是pip管理包
python·conda·pip
m0_730115112 小时前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
luffy54592 小时前
Rust语言入门-变量篇
开发语言·后端·rust
FreakStudio2 小时前
MicroPython+PycoClaw,3 分钟搞定 ESP32 跑上 OpenClaw!
python·单片机·嵌入式·电子diy
2301_807367192 小时前
C++中的模板方法模式
开发语言·c++·算法
weixin_537590452 小时前
《C程序语言设计》练习答案(练习1-3)
c语言·开发语言
罗罗攀2 小时前
PyTorch学习笔记|张量的广播和科学运算
人工智能·pytorch·笔记·python·学习
m0_459252462 小时前
fastadmin动态渲染统计信息
开发语言·前端·javascript·php