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()}")
相关推荐
无风听海10 分钟前
C# 隐式转换深度解析
java·开发语言·c#
涛声依旧-底层原理研究所1 小时前
残差连接与层归一化通俗易懂的详解
人工智能·python·神经网络·transformer
一只大袋鼠1 小时前
Git 进阶(二):分支管理、暂存栈、远程仓库与多人协作
java·开发语言·git
csdn_aspnet1 小时前
Python 算法快闪 LeetCode 编号 70 - 爬楼梯
python·算法·leetcode·职场和发展
fantasy_arch1 小时前
pytorch人脸匹配模型
人工智能·pytorch·python
熊猫_豆豆1 小时前
广义相对论水星近日点进动完整详细数学推导
python·天体·广义相对论
LuminousCPP1 小时前
数据结构 - 线性表第四篇:C 语言通讯录优化升级全记录(踩坑 + 思考)
c语言·开发语言·数据结构·经验分享·笔记·学习
web3.08889992 小时前
1688 图搜接口(item_search_img / 拍立淘) 接入方法
开发语言·python
AI算法沐枫2 小时前
深度学习python代码处理科研测序数据
数据结构·人工智能·python·深度学习·决策树·机器学习·线性回归
один but you2 小时前
从可变参数到 emplace:现代 C++ 性能优化的核心组合
java·开发语言