Python3 数据结构
列表进阶用法、栈与队列、列表推导式、元组、集合、字典与遍历技巧。
列表
The list is the workhorse mutable sequence. Its methods cover the whole CRUD surface: count, index, insert, remove, reverse, sort. All mutate in place and return None.
a = [66.25, 333, -1, 333, 1, 1234.5]
print(a.count(333), a.count(66.25), a.count('x'))
a.insert(2, -1)
a.append(333)
print(a)
print(a.index(333))
a.remove(333)
print(a)
a.reverse()
print(a)
a.sort()
print(a)2 1 0
[66.25, 333, -1, -1, 333, 1, 1234.5, 333]
1
[66.25, -1, -1, 333, 1, 1234.5, 333]
[333, 1234.5, 1, 333, -1, -1, 66.25]
[-1, -1, 1, 66.25, 333, 333, 1234.5]将列表当做栈使用
A stack is last-in-first-out. Use append() to push and pop() to pop — both act on the tail in O(1), so a plain list already is a stack.
stack = [3, 4, 5]
stack.append(6)
stack.append(7)
print(stack)
print(stack.pop())
print(stack)
print(stack.pop())
print(stack.pop())
print(stack)[3, 4, 5, 6, 7]
7
[3, 4, 5, 6]
6
5
[3, 4]将列表当作队列使用
A queue is first-in-first-out. pop(0) / insert(0, x) on a list is O(n) because every element shifts; use collections.deque with append / popleft for O(1) at both ends.
from collections import deque
queue = deque(["Eric", "John", "Michael"])
queue.append("Terry")
queue.append("Graham")
print(queue.popleft())
print(queue.popleft())
print(queue)Eric
John
deque(['Michael', 'Terry', 'Graham'])deque(maxlen=n) — the oldest item is dropped automatically once the limit is reached.列表推导式
A list comprehension replaces "empty list + loop + append" with [expr for var in iterable if cond]. It supports multiple nested for clauses and several conditions.
squares = []
for x in range(10):
squares.append(x ** 2)
print(squares)
squares = [x ** 2 for x in range(10)]
print(squares)
print([(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y])
print([-x for x in range(5)])
print([x for x in range(20) if x % 3 == 0])[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
[0, -1, -2, -3, -4]
[0, 3, 6, 9, 12, 15, 18]嵌套列表解析
A 2-D list can be transposed by iterating rows and picking columns. In [[row[i] for row in matrix] for i in range(4)] the outer comprehension produces the final list and the inner one builds each row.
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
print([[row[i] for row in matrix] for i in range(4)])
print(list(zip(*matrix)))[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]del 语句
del removes by position, can delete a slice, empty the whole list, or even unbind the name itself. It is a statement, not a method.
a = [-1, 1, 66.25, 333, 333, 1234.5]
del a[0]
print(a)
del a[2:4]
print(a)
del a[:]
print(a)[1, 66.25, 333, 333, 1234.5]
[1, 66.25, 1234.5]
[]元组和序列
A tuple is defined by commas and is immutable — parentheses are just cosmetic. It can hold mixed types, supports unpacking, and being immutable it may serve as a dict key or set member.
t = 12345, 54321, 'hello!'
print(t[0])
print(t)
u = t, (1, 2, 3, 4, 5)
print(u)
x, y, z = t
print(x, y, z)
s = {t}
print(s)12345
(12345, 54321, 'hello!')
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
12345 54321 hello!
{(12345, 54321, 'hello!')}集合
A set is an unordered collection of unique items, built with {} or set(). It supports - difference, | union, & intersection and ^ symmetric difference — ideal for dedup and set algebra.
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
print(sorted(basket))
print('orange' in basket, 'crabgrass' in basket)
a = set('abracadabra')
b = set('alacazam')
print(sorted(a))
print(sorted(a - b))
print(sorted(a | b))
print(sorted(a & b))
print(sorted(a ^ b))['apple', 'banana', 'orange', 'pear']
True False
['a', 'b', 'c', 'd', 'r']
['b', 'd', 'r']
['a', 'b', 'c', 'd', 'l', 'm', 'r', 'z']
['a', 'c']
['b', 'd', 'l', 'm', 'r', 'z']set(), not {} — that is an empty dict. Set members must be hashable: lists are out, tuples are fine.字典
A dict maps keys to values via {key: value}. Keys must be hashable and unique; values are unrestricted. Since 3.7 iteration follows insertion order, and in tests keys.
tel = {'jack': 4098, 'sape': 4139}
tel['guido'] = 4127
print(tel)
print(tel['jack'])
del tel['sape']
tel['irv'] = 4127
print(tel)
print(list(tel))
print(sorted(tel))
print('guido' in tel, 'jack' not in tel)
print(dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]))
print({x: x ** 2 for x in (2, 4, 6)})
print(dict(sape=4139, guido=4127, jack=4098)){'jack': 4098, 'sape': 4139, 'guido': 4127}
4098
{'jack': 4098, 'guido': 4127, 'irv': 4127}
['jack', 'guido', 'irv']
['guido', 'irv', 'jack']
True False
{'sape': 4139, 'guido': 4127, 'jack': 4098}
{2: 4, 4: 16, 6: 36}
{'sape': 4139, 'guido': 4127, 'jack': 4098}遍历技巧
Use items() for key/value pairs, enumerate() for indices, zip() to walk sequences in parallel, reversed() to go backwards, and sorted(set(...)) for deduplicated ordered output.
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
print(k, v)
for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))
for i in reversed(range(1, 10, 2)):
print(i, end=' ')
print()
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f)gallahad the pure
robin the brave
0 tic
1 tac
2 toe
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
9 7 5 3 1
apple
banana
orange
pear参阅文档
That covers the vast majority of everyday data-structure work. For the full definitions and edge cases see the official docs on built-in types, the collections module (deque, Counter, defaultdict, namedtuple) and specialised containers such as heapq, bisect, array.
- Built-in Types — list, tuple, set, dict
- collections — deque, Counter, defaultdict, namedtuple
- heapq / bisect — priority queues and binary search
- array / struct — compact numeric storage
列表
列表是最常用的可变序列,内置方法覆盖增删改查:count 计数、index 找位置、insert 插入、remove 按值删、reverse 反转、sort 排序。所有方法都就地修改,返回 None。
a = [66.25, 333, -1, 333, 1, 1234.5]
print(a.count(333), a.count(66.25), a.count('x'))
a.insert(2, -1)
a.append(333)
print(a)
print(a.index(333))
a.remove(333)
print(a)
a.reverse()
print(a)
a.sort()
print(a)2 1 0
[66.25, 333, -1, -1, 333, 1, 1234.5, 333]
1
[66.25, -1, -1, 333, 1, 1234.5, 333]
[333, 1234.5, 1, 333, -1, -1, 66.25]
[-1, -1, 1, 66.25, 333, 333, 1234.5]将列表当做栈使用
栈是「后进先出」:用 append() 压栈、pop() 弹栈,两者都在列表尾部操作,时间复杂度 O(1),所以列表天然就是栈。
stack = [3, 4, 5]
stack.append(6)
stack.append(7)
print(stack)
print(stack.pop())
print(stack)
print(stack.pop())
print(stack.pop())
print(stack)[3, 4, 5, 6, 7]
7
[3, 4, 5, 6]
6
5
[3, 4]将列表当作队列使用
队列是「先进先出」。用列表头部 pop(0) 或 insert(0, x) 会很慢(要整体搬移元素,O(n)),正确做法是用 collections.deque 的 append / popleft,两端都是 O(1)。
from collections import deque
queue = deque(["Eric", "John", "Michael"])
queue.append("Terry")
queue.append("Graham")
print(queue.popleft())
print(queue.popleft())
print(queue)Eric
John
deque(['Michael', 'Terry', 'Graham'])deque(maxlen=n):超出长度会自动从另一端丢弃最旧的元素。列表推导式
列表推导式用一行表达式替代「建空列表 + 循环 + append」,语法是 [表达式 for 变量 in 可迭代对象 if 条件]。它可以多层 for 嵌套,条件也可以多个。
squares = []
for x in range(10):
squares.append(x ** 2)
print(squares)
squares = [x ** 2 for x in range(10)]
print(squares)
print([(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y])
print([-x for x in range(5)])
print([x for x in range(20) if x % 3 == 0])[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
[0, -1, -2, -3, -4]
[0, 3, 6, 9, 12, 15, 18]嵌套列表解析
二维列表可以按行遍历再取列,实现转置。写成 [[row[i] for row in matrix] for i in range(4)] 时,外层推导式的结果才是最终列表,内层每次产出一行。
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
print([[row[i] for row in matrix] for i in range(4)])
print(list(zip(*matrix)))[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]del 语句
del 按位置删除元素,也能删切片、清空整个列表,甚至删除变量名本身。它是语句而不是方法,作用于「名字所指向的容器内容」。
a = [-1, 1, 66.25, 333, 333, 1234.5]
del a[0]
print(a)
del a[2:4]
print(a)
del a[:]
print(a)[1, 66.25, 333, 333, 1234.5]
[1, 66.25, 1234.5]
[]元组和序列
元组用逗号定义,不可变,通常用小括号括起来。它可以装不同类型的数据、支持解包,且因为不可变所以能作为字典的键或放进集合。
t = 12345, 54321, 'hello!'
print(t[0])
print(t)
u = t, (1, 2, 3, 4, 5)
print(u)
x, y, z = t
print(x, y, z)
s = {t}
print(s)12345
(12345, 54321, 'hello!')
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
12345 54321 hello!
{(12345, 54321, 'hello!')}集合
集合是无序、不重复的元素集,用 {} 或 set() 创建。它支持 - 差集、| 并集、& 交集、^ 对称差,是去重和集合运算的首选。
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
print(sorted(basket))
print('orange' in basket, 'crabgrass' in basket)
a = set('abracadabra')
b = set('alacazam')
print(sorted(a))
print(sorted(a - b))
print(sorted(a | b))
print(sorted(a & b))
print(sorted(a ^ b))['apple', 'banana', 'orange', 'pear']
True False
['a', 'b', 'c', 'd', 'r']
['b', 'd', 'r']
['a', 'b', 'c', 'd', 'l', 'm', 'r', 'z']
['a', 'c']
['b', 'd', 'l', 'm', 'r', 'z']set(),{} 是空字典。集合元素必须可哈希,所以列表不能放进去,元组可以。字典
字典是键值对映射,用 {key: value} 创建。键必须可哈希且唯一,值任意。3.7 起字典保证按插入顺序迭代,in 判断的是键。
tel = {'jack': 4098, 'sape': 4139}
tel['guido'] = 4127
print(tel)
print(tel['jack'])
del tel['sape']
tel['irv'] = 4127
print(tel)
print(list(tel))
print(sorted(tel))
print('guido' in tel, 'jack' not in tel)
print(dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]))
print({x: x ** 2 for x in (2, 4, 6)})
print(dict(sape=4139, guido=4127, jack=4098)){'jack': 4098, 'sape': 4139, 'guido': 4127}
4098
{'jack': 4098, 'guido': 4127, 'irv': 4127}
['jack', 'guido', 'irv']
['guido', 'irv', 'jack']
True False
{'sape': 4139, 'guido': 4127, 'jack': 4098}
{2: 4, 4: 16, 6: 36}
{'sape': 4139, 'guido': 4127, 'jack': 4098}遍历技巧
遍历字典用 items() 同时取键值;需要下标用 enumerate();并行遍历多个序列用 zip();倒序遍历用 reversed();去重后有序输出用 sorted(set(...))。
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
print(k, v)
for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))
for i in reversed(range(1, 10, 2)):
print(i, end=' ')
print()
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f)gallahad the pure
robin the brave
0 tic
1 tac
2 toe
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
9 7 5 3 1
apple
banana
orange
pear参阅文档
以上内容覆盖了日常使用的绝大部分数据结构操作。更完整的定义与边界情况请查阅官方文档:内置类型、collections 模块(deque、Counter、defaultdict、namedtuple)以及 heapq、bisect、array 等专用容器。
- 内置类型 —— 列表、元组、集合、字典
- collections —— deque、Counter、defaultdict、namedtuple
- heapq / bisect —— 优先队列与二分查找
- array / struct —— 紧凑数值存储