在工作中使用链表以及Python中的实现
“我们在日常工作中可能不会使用那些花哨的数据结构,比如链表、二叉树、AVL树或其他什么。”
^ 你在学习数据结构和算法时可能经常听到这样的说法——虽然这些数据结构和算法可能频繁出现在编码面试中,但在实际工作和构建应用程序时,我们很少会用到这些花哨的数据结构和算法。
但链表确实有一个非常有用的场景!
队列
queue = [start]
while len(queue) > 0:
current = queue.pop(0)
# 对队列执行一些操作
# 进行广度优先搜索(BFS)或深度优先搜索(DFS)
^ 如果我们需要进行某种图搜索,我们可能会使用队列(或栈)来存放我们未来需要搜索的节点。我们可能会简单地使用普通的列表来代替队列。
一些问题:
- 从队列开头弹出元素(
queue.pop(0))需要 O(n) 时间 - 从队列末尾弹出元素(
queue.pop())需要 O(1) 时间 - 在队列开头添加元素(
queue.insert(0, element))需要 O(n) 时间 - 在队列末尾添加元素(
queue.append(element))需要 O(1) 时间
需要注意的是,从列表的开头添加或弹出元素需要线性时间,这在我们有大量数据时可能会成为一个问题。
使用链表代替列表
from collections import deque
deque 是一个双端队列。以下所有操作都可以在常数时间 O(1) 内完成:
- 向右侧添加新元素
- 向左侧添加新元素
- 从右侧弹出元素
- 从左侧弹出元素
from collections import deque
queue = deque([1, 2, 3])
queue.append(4) # O(1) 时间
print(queue) # deque([1, 2, 3, 4])
queue.appendleft(100) # O(1) 时间
print(queue) # deque([100, 1, 2, 3, 4])
x = queue.pop() # O(1) 时间
print(queue, x) # deque([100, 1, 2, 3]) 4
y = queue.popleft() # O(1) 时间
print(queue, y) # deque([1, 2, 3]) 100
deque 是一种链表——一种同时记录起始节点和结束节点的链表——因此,从队列的任一端添加或弹出元素都只需常数时间。
何时应该使用双端队列而不是列表?
如果我们有一个包含许多元素的队列,并且我们需要从队列的两端添加/删除元素,那么使用 deque 会更合适。