二叉树的遍历方法有五种:(1)前序遍历(2)中序遍历(3)后序遍历(4)深度优先遍历(5)广度优先遍历(层次遍历)单这些遍历算法并不具有通用性。需要使用更通用的方法访问结点对象,于是我们在遍历二叉树上添加迭代功能。
为了方便遍历二叉树的所有结点,我们想为二叉树添加迭代功能,以实现通用的迭代工具。
二叉树的遍历算法
我们定义二叉树的结点:
1 2 3 4 5 6
| class Node: def __init__(self, value): self.value = value self.left = None self.right = None
|
Pyton语法简洁,我们使用Python作伪代码
前序遍历
1 2 3 4 5 6 7 8
| def preorder_traverse(node): if not node: return do(node) if node.left: inorder_traverse(node.left) if node.right: inorder_traverse(node.right)
|
中序遍历
1 2 3 4 5 6 7 8
| def inorder_traverse(node): if not node: return if node.left: inorder_traverse(node.left) do(node) if node.right: inorder_traverse(node.right)
|
后序遍历
1 2 3 4 5 6 7 8
| def deorder_traverse(node): if not node: return if node.left: inorder_traverse(node.left) if node.right: inorder_traverse(node.right) do(node)
|
可以看到这三种遍历方法很相似,只是处理结点的位置不一样,可见递归的优雅
深度优先遍历
我们使用一个栈结构做容器以实现深度优先遍历
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Stack:
def __init__(self): self._q = []
def push(self, value): self._q.push(value)
def pop(self): return self._q.pop()
def empty(self): return len(self._q) == 0
|
1 2 3 4 5 6 7 8 9 10 11 12
| def traverse_tree_depth(tree): if not tree: return stack = Stack() stack.push(tree) while not stack.empty(): p_node = stack.pop() do_something(p_node) if p_node.left: stack.push(p_node.left) if p_node.right: stack.push(p_node.left)
|
广度优先遍历算法(层次遍历)
广度优先遍历算法参考旧文从上往下打印二叉树,具体的实现如下
实现一个简单队列做容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Queue: def __init__(self): self._q = []
def put(self, item): self._q.append(item)
def get(self): item = self._q[0] del self._q[0] return item
def empty(self): return len(self._q) == 0
|
层次遍历算法
1 2 3 4 5 6 7 8 9 10
| def print_tree_from_top_to_bottom(root): queue = Queue() queue.put(root) while not queue.empty(): node = queue.get() print(node) if node.left: queue.put(node.left) if node.right: queue.put(node.right)
|
二叉树迭代算法
上面五种二叉树的遍历算法中,并没有通用性,我们需要实现了do_someting
函数,以供遍历二叉树的函数调用,但在do_someting
函数的需求没有明确前,遍历二叉树的算法无法实现封装。为了解决这个问题,在Python里可以使用迭代器。
下面以中序遍历和深度优先遍历算法为例,其他的实现思路是一样的。
1 2 3 4 5 6 7
| def inorder_traverse(tree): if tree: for x in inorder_traverse(tree.left): yield x yield tree for x in inorder_traverse(tree.right): yield x
|
这样,在没有明确do_someting
的需求是实现通用的二叉树遍历迭代器,使用方法如下
1 2
| for node in inorder_traverse(tree): do_someting(node)
|
深度优先的遍历过程有类似的处理
1 2 3 4 5 6 7 8 9 10 11
| def traverse_tree_depth(tree): if tree: stack = Stack() stack.push(tree) while not stack.empty(): p_node = stack.pop() if p_node.left: stack.push(p_node.left) if p_node.right: stack.push(p_node.left) yield p_node
|
我们甚至可以通过一类类封装上面的过程,通过一个类封装实现树的五种遍历方法。采用Mixin方式,如果树类继承了下面实现的类,那么它就拥有了五种遍历树的方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| class TreeIterMixin:
def __init__(self, tree): self._root = tree
def preorder_traverse(self): for x in self._preorder(self._root): yield x
def _preorder(self, node): if node: yield node for x in self._preorder(node.left): yield x for x in self._preorder(node.right): yield x
def inorder_traverse(self): for x in self._inorder(self._root): yield x
def _inorder(self, node): if node: for x in self._preorder(node.left): yield x yield node for x in self._preorder(node.right): yield x
def postorder_traverse(self): for x in self._inorder(self._root): yield x
def _postorder(self, node): if node: for x in self._preorder(node.left): yield x for x in self._preorder(node.right): yield x yield node
def depth_first_order_traverse(self): if self._root: stack = Stack() stack.push(self._root) while not stack.empty(): node = stack.pop() if node.left: stack.push(node.left) if node.right: stack.push(node.right) yield node
def breadth_first_order_traverse(self): if self._root: queue = Queue() queue.push(self._root) while not queue.empty(): node = queue.pop() if node.left: queue.push(node.left) if node.right: queue.push(node.right) yield node
|
上面就是Python的二叉树遍历的迭代算法的。后期更新Go版本。
完。
��。