欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Python】二叉树的广度优先搜索和深度优先搜索

程序员文章站 2022-05-22 20:56:49
...

1. 什么是二叉树

二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

2. 本文用到的二叉树例子

      1
     /  \
   2      3
 /  \    /  \
4    5  6    7

3. 什么是广度优先搜索(BFS)

BFS(Breath First Search),概念可以自行百度,通俗的讲就是,依次遍历树每一层节点,按照上面给出的例子,预期得到的是:[1, 2, 3, 4, 5, 6, 7]

4. 什么是深度优先搜索(DFS)

DFS(Deep First Search),概念可以自行百度,通俗的讲就是,对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次,按照上面给出的例子,预期得到的是:[1, 2, 4, 5, 3, 6, 7]

5. 使用队列实现BFS

Python常用的有两个队列类,线程安全的FIFO队列(First in First out 先进先出)queue.Queue,多进程中使用的队列 multiprocessing.Queue。其实,Python中的列表也可以实现队列的先进先出的功能(进队列用append,出队列取第1个元素),只不过它不是线程安全的。为了方便理解,我们用列表来模拟队列实现BFS。

# 先定义一个二叉树的节点类
class TreeNode:
    def __init__(self, x):
        self.val = x  # 该节点的值
        self.left = None # 该节点的左子树
        self.right = None # 该节点的右子树
        
# 构造例子中的二叉树
"""
      1
    /   \
   2      3
 /  \    /  \
4    5  6    7
"""
root = TreeNode(1)
root.left = TreeNode(2)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
root.right = TreeNode(3)
root.right.left = TreeNode(6)
root.right.right = TreeNode(7)

# 广度优先搜索
def bfs(root):
    res = []
    q = [root] # 先把根节点放进队列中
    while q:  # 当队列不为空时进入循环体
        current_node = q.pop(0)  # 取出队列的第一个节点
        res.append(current_node.val)  # 把该节点的值加入结果集
        if current_node.left:   # 如果左子树不为空,就加入队列
            q.append(current_node.left)
        if current_node.right:  # 如果右子树不为空,就加入队列
            q.append(current_node.right)
    return res

print(bfs(root))
# 输出:[1, 2, 3, 4, 5, 6, 7]

6. 使用栈实现DFS

同样的,列表也可以模拟栈先进后出的功能(入栈使用append,出栈取最后一个元素)。我们先把根节点压入栈中,然后判断栈是否为空,不为空则进入循环体,取出栈顶节点,然后依次把栈顶节点的右子树和左子树压入栈中,因为栈先进后出的原则,这样取出来的顺序就是 左 - 右 - 根。

# 二叉树直接复用上面的例子,不再重复构建

# 深度优先搜索
def dfs(root):
    res = []
    q = [root]  # 先把根节点放进栈中
    while q:  # 当栈不为空时进入循环体
        current_node = q.pop()  # 取出栈顶节点
        res.append(current_node.val)  # 把该节点的值加入结果集
        if current_node.right:  # 如果右子树不为空,就压入栈
            q.append(current_node.right)
        if current_node.left:  # 如果左子树不为空,就压入栈
            q.append(current_node.left)
    return res
    
print(dfs(root))
# 输出:[1, 2, 4, 5, 3, 6, 7]

7. 使用递归实现DFS

# 二叉树直接复用上面的例子,不再重复构建

res = []
# 使用递归实现深度优先搜索
def dfs_recur(node):
    if not node: # 递归结束的条件是当该节点为None时
        return
    res.append(node.val) # 把该节点的值加入结果集
    dfs_recur(node.left) # 对左子树进行递归
    dfs_recur(node.right) # 对右子树进行递归
    
dfs_recur(root)
print(res)
# 输出:[1, 2, 4, 5, 3, 6, 7]

更多精彩 http://www.17hf.online/blog/article/1/10