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()}")
相关推荐
Scott9999HH4 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海5 小时前
python 列表、元组、集合和字典
开发语言·python
二十雨辰5 小时前
[爬虫]-Urllib
爬虫·python
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
玉鸯7 小时前
Agent Hook:在概率推理之上,为 Agent 叠加确定性控制
python·langchain·agent
weixin_446260858 小时前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
我的xiaodoujiao8 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest