在工作中使用链表以及Python中的实现

87 阅读2分钟

在工作中使用链表以及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 会更合适。