如何遍历一棵树(基于Python的理解以及实现)

文章目录

  • 如何遍历一棵树
    • 1.宽度优先搜索(BFS)/广度优先遍历
    • 2.深度优先搜索(DFS)
      • (1)前序遍历序列:[**根节点**,左子树,右子树]
      • (2)中序遍历序列:[左子树,**根节点**,右子树]
      • (3)后序遍历序列:[左子树,右子树,**根节点**]
    • 3.Python编程实现
      • 前序遍历/先序遍历
      • 后序遍历
      • 广度优先遍历
      • 中序遍历

如何遍历一棵树

有两种通用的遍历树的策略:

1.宽度优先搜索(BFS)/广度优先遍历

我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到。
BFS 需要借助队列来实现 树的广度优先遍历 而不需要迭代
相关代码:
Leetcode:面试题32 - I. 从上到下打印二叉树
面试题32 - II. 从上到下打印二叉树 II
面试题32 - III. 从上到下打印二叉树 III

2.深度优先搜索(DFS)

在这个策略中,我们采用深度作为优先级,以便从跟开始一直到达某个确定的叶子,然后再返回根到达另一个分支。

从根开始计算,到找到位于某个节点的解,**回溯法(深度优先搜索)**作为最基本的搜索算法,其采用了一种“**一只向下走,走不通就掉头”**的思想(体会“回溯”二字),相当于采用了先根遍历的方法来构造搜索树。

深度优先搜索策略又可以根据根节点、左子树和右子树的相对顺序被细分为前序遍历中序遍历后序遍历

(1)前序遍历序列:[根节点,左子树,右子树]

(2)中序遍历序列:[左子树,根节点,右子树]

== 拿个铅垂线从左到右依次划过==

(3)后序遍历序列:[左子树,右子树,根节点]

下图中的顶点按照访问的顺序编号,按照 1-2-3-4-5 的顺序来比较不同的策略。
如何遍历一棵树(基于Python的理解以及实现)_第1张图片

3.Python编程实现

LeetCode中相关题目的Python编程实现:
(1)105. 从前序与中序遍历序列构造二叉树 \ 面试题07. 重建二叉树
(2)基于Python实现的链式二叉树结构

前序遍历/先序遍历

通过调用树的preorder函数,生成一个关于树的前序迭代器。(yield函数)

def preorder(self):
    """生成树的前序遍历序列"""
    if not self.is_empty():
        for p in self._subtree_preorder(self.root()):  # 开始迭代
            yield p

def _subtree_preorder(self,p):
    yield p                              # 生成根节点
    for c in self.children(p):           # 对每个根节点的左右子树都进行迭代 直至节点为叶节点
        for other in self._subtree_preorder(c):
            yield other
    

后序遍历

前序遍历和后续遍历的区别在于递归查到子树之后,再生成根节点

def postorder(self):
    """生成树的后序遍历序列"""
    if not self.is_empty():
        for p in self._subtree_preorder(self.root()):  # 开始迭代
            yield p

def _subtree_preorder(self,p):
    for c in self.children(p):           # 对每个根节点的左右子树都进行迭代 直至节点为叶节点
        for other in self._subtree_preorder(c):
            yield other
    yield p                              # 生成根节点

广度优先遍历

BFS不是递归,其借助于队列来管理递归。

from collections import deque
def bfs(self):
	if not self.is_empty():
		a=deque()               # 创建一个空队列
		a.append(self.root())   # 从根节点开始
		while not a.is_empty(): # 循环截止条件是队列pop为空
			p=a.popleft()		# 弹出根节点
			yield p
			for c in self.children(p): # 放入每个根节点的子节点 
				a.append(c)

中序遍历

前三中方法可以用于树的任何结构中,而中序遍历,只能用于二叉树中。
过程和前序、后序遍历类似,更改根节点和左右子树遍历的位置即可

def inorder(self):
	if not self.is_empty():
		for p in self._subtree_inorder(self.root()):
			yield p

def _subtree_inorder(self,p):
	if self.left(p) is not None:          # 遍历左子树
		for other in self._suntree_inorder(self.left(p)):
			yield other
	yield p										# 遍历根节点																		
	if self.right(p) is not None:				# 遍历右子树
		for other in self._suntree_inorder(self.right(p)):
			yield other
	

你可能感兴趣的:(算法,python)