已发布·持续改进
Algorithm
了解数组、链表、栈、队列和哈希表的工作原理与各操作的时间复杂度,学会根据场景选择合适的数据结构。
数据结构是数据在内存中的组织方式,以及在这种组织方式上能够高效完成的操作。本主题介绍几乎所有程序都会用到的五种基础结构:数组与动态数组、链表、栈、队列与双端队列,以及哈希表。同时还会讲解连续内存与链式内存的区别、哈希函数、哈希冲突和负载因子。
选择哪种数据结构,决定了同一个操作是 O(1) 还是 O(n)。用从列表头部删除元素的方式实现队列,或者在列表中做成员检查,数据一多程序就会明显变慢。了解 Python 的 list、deque、dict、set,C++ 的 vector、deque、unordered_map,Java 的 ArrayList、ArrayDeque、HashMap,以及 TypeScript 的 Array、Map、Set 背后究竟是什么结构,就能提前避开这些陷阱,这也是技术面试最先考查的内容。
建议先用小例子手动推演每种结构,看清内存中到底移动了什么。接着亲手实现栈、环形缓冲区队列和拉链法哈希表,把各操作的复杂度整理成表格并用计时器实测。最后通过练习题训练为每个问题挑选合适结构的能力。
数组支持按下标 O(1) 访问且缓存友好;链表可以在已持有的节点旁边以 O(1) 插入和删除。
动态数组按固定倍数扩容并复制元素,因此偶尔出现的昂贵追加平摊下来仍是 O(1)。
栈取出最新的元素,队列取出最早的元素。双端队列和环形缓冲区能让两端的操作都达到 O(1)。
哈希表把键映射到桶中,平均 O(1) 完成查找;用拉链法等方式处理冲突,负载因子超过上限时进行扩容。
用拉链法实现的哈希表:用键的哈希值对桶数取模来选择桶,键已存在时只替换值,负载因子超过 0.75 时把桶数翻倍并重新插入所有键值对。脚本还演示了把列表当作栈、把 deque 当作队列的用法。
data_structures.py
from collections import deque
class HashMap:
"""Separate chaining: each bucket is a list of (key, value) pairs."""
def __init__(self, capacity=8):
self.buckets = [[] for _ in range(capacity)]
self.size = 0
def _bucket(self, key):
return self.buckets[hash(key) % len(self.buckets)]
def put(self, key, value):
bucket = self._bucket(key)
for i, (k, _) in enumerate(bucket):
if k == key:
bucket[i] = (key, value)
return
bucket.append((key, value))
self.size += 1
if self.size > 0.75 * len(self.buckets): # load factor limit
old = self.buckets
self.buckets = [[] for _ in range(2 * len(old))]
for pairs in old:
for k, v in pairs:
self._bucket(k).append((k, v))
def get(self, key, default=None):
for k, v in self._bucket(key):
if k == key:
return v
return default
stack = [1, 2, 3]
stack.append(4)
print("stack pop:", stack.pop()) # 4 (LIFO)
queue = deque([1, 2, 3])
queue.append(4)
print("queue popleft:", queue.popleft()) # 1 (FIFO)
ages = HashMap()
for name, age in [("ada", 36), ("alan", 41), ("grace", 85)]:
ages.put(name, age)
ages.put("ada", 37)
print("ada:", ages.get("ada"), "size:", ages.size) # ada: 37 size: 3
python data_structures.py共六章,带你从安装一步步了解 基础数据结构 的核心概念。
在这里提问、分享经验,交流关于 基础数据结构 的看法。
还没有讨论。来发起第一个吧。
0 条评论
登录 · 登录后即可发表评论。
来发表第一条评论吧。