Python 字典为什么查询高效

Python 字典(dict)之所以查询效率非常高(平均时间复杂度为 O(1)),主要归功于其底层实现——哈希表(Hash Table)

1. 核心:哈希表(Hash Table)

字典本质上是一个哈希表。哈希表是一种通过键(key) 直接映射到值(value) 存储位置的数据结构。

工作流程:
  • 哈希函数(Hash Function)
    • 当你向字典中插入一个键值对(如 d['name'] = 'Alice')时,Python 会先对键 'name' 调用其 __hash__() 方法,得到一个整数,称为哈希值(hash value)
    • 这个哈希值是确定性的:同一个键,每次计算得到的哈希值都相同。
    • 不可变类型(如 str, int, tuple)都有 __hash__ 方法,因此可以作为字典的键;而可变类型(如 list, dict)没有,所以不能作为键。
  • 索引计算(Indexing)
    • 哈希值通常是一个很大的整数,不能直接用作数组下标。
    • Python 会将哈希值通过一个函数(通常是取模运算)映射到哈希表的槽位(slot) 索引上。例如:index = hash(key) % table_size
  • 存储/查找
    • Python 直接访问计算出的索引位置,将值存储进去(插入)或读取出来(查找)。
    • 由于数组的索引访问是 O(1) 操作,所以字典的查找/插入/删除平均也是 O(1)。

2. 处理哈希冲突(Collision)

不同的键可能产生相同的哈希值(或映射到同一索引),这称为哈希冲突。Python 字典使用了两种主要技术来解决:

a. 开放寻址法(Open Addressing)
  • Python 字典主要使用基于开放寻址的哈希表
  • 当目标槽位已被占用时,它会按照一定的探测序列(如线性探测、二次探测)寻找下一个空闲槽位。
  • Python 使用了一种优化的探测方式,能有效减少“聚集”(clustering)问题。
b. 键值对存储结构
  • Python 字典的底层结构设计巧妙,它将哈希值、键、值作为一个整体存储。
  • 在查找时,即使索引位置被占用,Python 会先比较哈希值,如果不同则直接跳过;如果相同,再比较是否相等(==)。
  • 这种“先比哈希,再比键”的方式大大加快了查找速度,尤其是在哈希冲突较多时。

3. 动态扩容(Resizing)

  • 哈希表的大小是固定的,但字典是动态的。
  • 当字典中元素过多,导致装载因子(元素数 / 槽位数)过高时,哈希冲突概率上升,性能下降。
  • Python 会在装载因子达到一定阈值(如 2/3)时,自动扩容:创建一个更大的哈希表,并将所有键值对重新哈希到新表中。

Read more

C++ Vector算法精讲与底层探秘:从经典例题到性能优化全解析

C++ Vector算法精讲与底层探秘:从经典例题到性能优化全解析

前引:在C++标准模板库(STL)中,vector作为动态数组的实现,既是算法题解的基石,也是性能优化的关键战场。其连续内存布局、动态扩容机制和丰富的成员函数,使其在面试高频题(如LeetCode、洛谷)中频繁登场。本文聚焦 六大经典算法场景 (含杨辉三角、去重、结构体排序等),深入解析vector的 底层扩容策略 、 迭代器失效陷阱 及 内存管理优化技巧 ,结合代码复现与复杂度对比,帮助开发者从“会用”进阶到“用精” 目录 只出现一次的数字I 原理讲解  代码展示  杨辉三角 原理讲解   代码展示 电话号码字母组合 原理讲解 代码展示 整型去重 原理讲解   代码展示 找只出现一次的数字II 原理讲解 代码展示 只出现一次的数字III 编辑原理讲解 代码展示   编辑 只出现一次的数字I

By Ne0inhk
数据结构:手撕堆和哈希表,字符串哈希详解----小白也能懂

数据结构:手撕堆和哈希表,字符串哈希详解----小白也能懂

🎬 博主名称:个人主页 🔥 个人专栏: 《算法通关》,《Java讲解》 ⛺️心简单,世界就简单 序言 其实是想把这篇写到上一篇里面的,但是中途困了,趴桌子上睡着了,真是没招 这篇文章,来手撕 堆和哈希表,这一般面试可能会问到,我们来了解他的思想和思路也是比较舒服的 目录 序言 堆 堆的存储 堆有两个基本操作 1,down( x ) 2 , up( x ) 操作一:插入一个数 操作二:求集合中的最小值 操作三:删除最小值 操作四:删除任意一个元素 操作五:修改任意一个元素 题目模板练习1 题目模板练习二 总结: 哈希表 存储结构:拉链法 存储结构:开放寻址法 处理冲突思路: 查找 删除 总结

By Ne0inhk
【LeetCode面试题17.04】消失的数字

【LeetCode面试题17.04】消失的数字

刷爆LeetCode系列 * LeetCode面试题17.04:消失的数字 * github地址 * 前言 * 题目描述 * 题目与思路分析 * 目标分析 * 思路一:数组哈希 * 思路二:数学求和 * 思路三:位运算(异或) * 代码实现 * 思路一:数组哈希 * 思路二:数学求和 * 思路三:位运算 * 算法代码优化 * 结语 LeetCode面试题17.04:消失的数字 github地址 有梦想的电信狗 前言 本文用C++三种方法实现LeetCode面试题17.04:消失的数字 * 方法一:数组哈希 * 方法二:数学求和再相减 * 方法三:位运算 题目描述 题目链接:https://leetcode.cn/problems/missing-number-lcci/description/ 题目与思路分析

By Ne0inhk
Flutter for OpenHarmony:diffutil_dart 列表差异计算引擎,高性能 UI 局部刷新的秘密武器(Myers 算法) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:diffutil_dart 列表差异计算引擎,高性能 UI 局部刷新的秘密武器(Myers 算法) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 在 Flutter 开发中,我们经常遇到列表更新的场景: * 用户下拉刷新,服务器返回了新的 20 条数据,其中 18 条是旧的,2 条是新的,还有 1 条被删除了。 * 我们需要更新 ListView 或 SliverList。 直接调用 setState 重新构建整个 List 确实简单,但性能有损耗,而且会导致 Scroll 位置丢失、动画生硬。我们希望能够: * 只插入那 2 条新数据。 * 只移除那 1 条旧数据。 * 并伴随优雅的插入/移除动画(使用 AnimatedList)。 diffutil_dart 就是解决这个问题的算法库。

By Ne0inhk