Python 数据结构与语法速查笔记

文章总览:YuanDaiMa2048博客文章总览


🔗 查看完整专栏(LeetCode基础算法专栏

专栏文章

点击阅读:Python 数据结构与语法速查笔记

点击阅读:哈希表基础原理与题目说明

点击阅读:双指针基础原理与题目说明

点击阅读:滑动窗口基础原理与题目说明

点击阅读:队列与单调队列基础原理与题目说明

特别说明: 本文为个人的 LeetCode 刷题与学习笔记,内容仅供学习与交流使用,禁止转载或用于商业用途。需要强调的是,文中的题目解法不一定是最优解(可能存在时间或空间复杂度的进一步优化空间),主要目的是分享个人的解题思路与逻辑实现,仅供参考。 笔记内容为个人理解与总结,可能存在疏漏或偏差,欢迎读者自行甄别并交流探讨。

Python 数据结构与语法速查笔记

日常以Python开发或刷题时,熟练掌握并区分各种数据结构的底层表现和正确语法至关重要。本文对Python中常用的数据结构进行了统一格式的整理,方便对比与记忆。

一、栈 (Stack) - 使用 list

  • 特点 :后进先出(LIFO)。Python中没有专门的Stack类,直接使用列表 [] 即可实现栈的功能。
  • 适用场景:括号匹配、单调栈(求下一个更大元素)、DFS(深度优先搜索)迭代实现。

🛠️ 核心操作速查

操作类型 代码语法 时间复杂度 说明
创建/初始化 stack = [] O(1) 直接初始化为空列表
加入 (Push) stack.append(val) O(1) 在列表末尾添加元素(压栈)
删除 (Pop) val = stack.pop() O(1) 弹出并返回列表最后一个元素(出栈)
访问/查看 top = stack[-1] O(1) 查看栈顶元素(注意需先判空 if stack:

⚠️ 注意 :不要滥用 stack.insert(0, val)stack.pop(0) 来模拟栈底操作,这会导致 O(N) 的时间复杂度,请始终在尾部进行 appendpop

二、队列与双端队列 (Queue / Deque)

  • 特点 :先进先出(FIFO)或 双端操作。不要用 list 模拟队列 (因为 list.pop(0) 是 O(N) 复杂度),建议使用标准库的 collections.deque
  • 适用场景:BFS(广度优先搜索)、滑动窗口、维护区间状态。

🛠️ 核心操作速查

操作 语法 时间复杂度 说明
创建/初始化 deq = deque() O(1) from collections import deque
加入队尾 deq.append(x) O(1) 常规入队(尾部添加)
加入队首 deq.appendleft(x) O(1) 双端队列特有(头部添加)
删除队首 deq.popleft() O(1) 常规出队(FIFO),弹出头部
删除队尾 deq.pop() O(1) 双端队列特有,弹出尾部

三、哈希表 (Hash Table)

哈希表通过键值对快速存取,平均时间复杂度为 O(1)。在 Python 中分为四种常用类型:dictsetCounterdefaultdict

在 Python 底层,collections.Countercollections.defaultdict 本质上都是继承自 dict 的子类。因此,在执行删除操作时候,在字典中用的 delpop(),完全可以直接用在这两个数据结构上。

del 和 pop 的主要区别在于:

del hash_dict[key]:直接在内存中删除该键值对。但是,如果这个 key 在字典中不存在,它会无情地抛出 KeyError 报错。

val = hash_dict.pop(key, None):不仅会删除该键值对,还会把被删除的值返回给你。更重要的是,加上第二个参数(如 None)后,如果 key 不存在,它不会报错,而是返回 None,这可以避免很多因为边界条件引起的意外崩溃。

1. 字典 (dict)

  • 特点:标准的键值对(Key-Value)映射。
操作类型 代码语法 说明
创建/初始化 hash_dict = {} 初始化空字典
加入/更新 hash_dict[key] = val 若 key 存在则覆盖,不存在则创建
删除 val = hash_dict.pop(key, None) 安全删除并返回值。不存在时返回设定的 None
访问/查询 val = hash_dict.get(key, 0) 安全访问。不存在时返回设定的默认值 0,不报错

2. 集合 (set)

  • 特点 :无序且元素唯一的集合,主要用于去重和快速查找。
操作类型 代码语法 说明
创建/初始化 nums_set = set() 初始化空集合(注意不能用 {}
加入 nums_set.add(val) 添加单个元素,若已存在则忽略
删除 nums_set.discard(val) 安全删除。若元素不存在也不会报错
访问/查询 if val in nums_set: O(1) 判断元素是否存在

如果这个元素在集合中不存在,使用 nums_set.remove(val) 会抛出 KeyError 报错,而 nums_set.discard(val) 则什么都不会发生,所以 discard 更"安全",省去了先判断 if val in nums_set: 的步骤。

3. 计数器 (collections.Counter)

  • 特点:自带统计功能的哈希表,自动计算频率。
操作类型 代码语法 说明
创建/初始化 freq = Counter(nums) 传入列表等迭代器,返回 {元素: 频次} 字典
加入/修改 freq[key] += 1 增加频次,键不存在时默认从 0 开始加
高级操作 freq.most_common(k) 返回出现频次最高的 k 个元素:[(val, freq), ...]

4. 默认字典 (collections.defaultdict)

  • 特点:访问不存在的键时,会自动创建默认值,适合分组或构建邻接表。
操作类型 代码语法 说明
创建(列表默认) adj = defaultdict(list) 默认值为空列表 []
加入/修改 adj[node].append(neighbor) 直接 append,无需判断 node 键是否已存在
创建(数字默认) count = defaultdict(int) 默认值为数字 0

四、优先队列 / 堆 (Heap)

  • 特点 :底层是一棵完全二叉树,Python 内置的是小顶堆(根节点最小) 。基于普通的 list 实现。
  • 适用场景:动态求极值、Top K 问题。

🛠️ 核心操作速查

操作 语法 时间复杂度 说明
创建/初始化 heap = [] O(1) 底层载体也是普通列表
原址建堆 heapq.heapify(nums) O(N) 将无序列表直接原地转化为小顶堆
加入 (Push) heapq.heappush(heap, x) O(log N) 将 x 放入堆并自动调整维持堆性质
删除 (Pop) heapq.heappop(heap) O(log N) 弹出并返回堆顶(最小)元素
查看堆顶 heap[0] O(1) 索引 0 永远是堆顶极小值
大顶堆技巧 heappush(heap, -x) - 存入时取负数,弹出时再取负数恢复

五、有序数组

数组排序 (sortsorted)

操作类型 代码语法 时间复杂度 说明
原地排序 arr.sort() O(N log N) 直接在原列表上修改,无返回值。可加 reverse=True 实现降序
生成新排序列表 new_arr = sorted(arr) O(N log N) 不改变原列表,返回一个全新的已排序列表

六、自定义数据结构 (链表与树)

在刷题(如 LeetCode)中,链表和树通常需要自己定义类。

1. 单链表节点 (Linked List)

py 复制代码
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

# 创建与遍历演示
head = ListNode(1)
head.next = ListNode(2)

curr = head
while curr:
    print(curr.val)
    curr = curr.next

2. 二叉树节点 (Binary Tree)

py 复制代码
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# 创建与初始化演示
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)

数据结构在 CPython 底层的本质

[] 列表 ------ 本质:动态数组 (Dynamic Array)

  • 涵盖结构:普通列表、栈 (Stack)、堆 (Heap / heapq)、有序数组 (bisect)。
  • 原理解析:它不是链表,而是一块连续的内存空间,里面存的是指向实际对象的指针。当数组满了,它会申请一块更大的新内存,把旧数据拷贝过去(过度分配机制)。
  • 致命缺陷:因为是连续内存,如果你删除了第 0 个元素(pop(0)),后面的所有元素都要往前挪动一位,时间复杂度为 O(N)。但尾部的 append 和 pop() 只需操作指针,所以是 O(1)。

collections.deque (双端队列)

  • 涵盖结构:队列 (Queue)、滑动窗口。专门为了解决上述 [] (动态数组) 头部操作极慢的问题。
  • 原理解析:底层结构是块状双向链表 (Doubly Linked List of Blocks)。它由一个个固定大小的"块"组成,块之间用双向链表连接。在头部或尾部添加/删除元素时,只需在最边缘的块操作或新建块,不需要移动其他元素,实现严格的 O(1)。

{} 字典/集合 ------ 本质:哈希表 (Hash Table)

  • 涵盖结构:字典 (dict)、集合 (set)、计数器 (Counter)、默认字典 (defaultdict)。
  • 原理解析:通过哈希函数计算键(Key)的索引位置,实现 O(1) 的极速存取。Python 使用"开放寻址法"解决哈希冲突。
  • 注意:
    • {} 默认是空字典。空集合必须用 set()。
    • {"a": 1} 是字典, {1, 2} 是集合。

() 元组 ------ 本质:静态只读数组

  • 涵盖结构:不可变序列。
  • 原理解析:一旦创建,内存大小和内容就完全固定,不支持任何增删改操作。
  • 用途:正因为其不可变(可哈希),只有 () 可以作为 {} (字典/集合) 的 Key,而 [] 绝对不行(例如用 (x,y) 记录网格访问状态)。

💡 综合记忆口诀

  1. 栈要后出 :只用 [],只调 append()pop()
  2. 队要先出 :引 deque,尾进 append(),头出 popleft()
  3. 频率/哈希 :去重找 set,映射找 dict,防越界找 defaultdict,统计找 Counter
  4. 最值/Top K :引 heapq,默认小堆(取大变负),操作带前缀 heappush / heappop
相关推荐
m0_747854522 小时前
Python模型保存为ONNX格式_跨平台推理部署与加速技巧
jvm·数据库·python
程序员cxuan2 小时前
为什么 Claude 要求实名认证?
人工智能·后端·程序员
粉嘟小飞妹儿2 小时前
怎么关闭MongoDB不需要的HTTP管理接口及REST API
jvm·数据库·python
key_3_feng2 小时前
基于AI智能体的防火墙策略智能管理方案
人工智能·ai智能体
qq_206901392 小时前
c++如何将浮点数按指定精度写入文本_setprecision用法【实战】
jvm·数据库·python
2401_865439632 小时前
如何管理Oracle服务器的内核共享内存_shmmax与shmall计算
jvm·数据库·python
神州数码云基地2 小时前
AI助手语音交互:从技术到体验
人工智能·ai·语音识别·前端开发·tts·ai语音
EasyGBS2 小时前
国标GB28181视频平台EasyGBS新增HLS按需切片:告别资源空转,让安防视频效率拉满!
网络·人工智能·音视频
asdzx672 小时前
C#:从 URL 下载 PDF 文档到本地
开发语言·pdf·c#