已发布·持续改进
Algorithm
学习树的术语与遍历、二叉搜索树的查找、插入和删除,以及二叉堆与优先队列的原理、复杂度和实现代码。
树是一种从根节点出发、按父子关系分支的层次型数据结构。给二叉树加上“小的键在左、大的键在右”的规则,就得到二叉搜索树(BST);加上“父节点不大于子节点”的规则和完全二叉树的形状,就得到二叉堆。本主题集中讲解树的术语、四种遍历、二叉搜索树、平衡树、堆与优先队列。
树和堆是许多实际系统的骨架。数据库索引使用 B 树,C++ 的 std::map 和 Java 的 TreeMap 是红黑树,操作系统调度器、定时器以及 Dijkstra 最短路径都依赖树或堆。理解“高度决定性能”以及“堆可以放在一个数组里”,就能判断何时选用哪种结构,这些内容也是技术面试和算法笔试的常见考点。
建议先在纸上画一棵小树,手动走一遍前序、中序、后序和层序遍历。接着亲手实现二叉搜索树的插入、查找、删除以及堆的上浮和下沉,并弄清楚 heapify 为什么是 O(n)。最后用 Python heapq、C++ priority_queue、Java PriorityQueue 等标准工具解决前 K 大、合并有序列表等问题,巩固所学概念。
掌握根、叶、深度、高度等术语以及前序、中序、后序、层序遍历,就能读懂并解决大多数树的问题。
由于小的键在左、大的键在右,查找、插入和删除的时间与树高成正比,中序遍历可以得到有序序列。
输入有序时,二叉搜索树会退化成链表。AVL 树和红黑树通过旋转把高度维持在 O(log n)。
把完全二叉树存进数组,查看最小值为 O(1),插入和弹出为 O(log n),对整个数组建堆为 O(n)。
用 Node 类构造二叉搜索树:bst_insert 通过比较键找到空位挂上新节点,bst_search 用循环向下查找键。中序遍历的结果可以验证键是按升序排列的。MinHeap 用列表保存元素,push 时上浮、pop 时下沉来维持堆的性质,因此取出的值从小到大排列。
trees_and_heaps.py
# Binary search tree (insert/search) and a binary min-heap
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
def bst_insert(root, key):
if root is None:
return Node(key)
if key < root.key:
root.left = bst_insert(root.left, key)
elif key > root.key:
root.right = bst_insert(root.right, key)
return root # duplicates are ignored
def bst_search(root, key):
while root is not None and root.key != key:
root = root.left if key < root.key else root.right
return root is not None
def inorder(root, out):
if root is not None:
inorder(root.left, out)
out.append(root.key)
inorder(root.right, out)
return out
class MinHeap:
def __init__(self):
self.a = []
def push(self, x):
a = self.a
a.append(x)
i = len(a) - 1
while i > 0 and a[(i - 1) // 2] > a[i]: # sift up
p = (i - 1) // 2
a[i], a[p] = a[p], a[i]
i = p
def pop(self):
a = self.a
top, last = a[0], a.pop()
if a:
a[0] = last
i, n = 0, len(a)
while True: # sift down
small = i
for c in (2 * i + 1, 2 * i + 2):
if c < n and a[c] < a[small]:
small = c
if small == i:
break
a[i], a[small] = a[small], a[i]
i = small
return top
def __len__(self):
return len(self.a)
root = None
for k in [50, 30, 70, 20, 40, 60, 80]:
root = bst_insert(root, k)
print(inorder(root, [])) # [20, 30, 40, 50, 60, 70, 80]
print(bst_search(root, 60), bst_search(root, 65)) # True False
heap = MinHeap()
for x in [5, 3, 8, 1, 9, 2]:
heap.push(x)
print([heap.pop() for _ in range(len(heap))]) # [1, 2, 3, 5, 8, 9]
共六章,带你从安装一步步了解 树与堆 的核心概念。
在这里提问、分享经验,交流关于 树与堆 的看法。
还没有讨论。来发起第一个吧。
python trees_and_heaps.py
0 条评论
登录 · 登录后即可发表评论。
来发表第一条评论吧。