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

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

python二叉树广度优先遍历是指按照层次逐层遍历二叉树的节点。从根节点开始,一层一层地遍历每个节点,并按照从左到右的顺序依次访问它们。广度优先遍历可以使用队列来实现。具体步骤如下: 1. 创建一个空队列,并将根节点入队。 2. 循环执行以下步骤,直到队列为空: a. 出队一个节点。 b. 访问该节点。 c. 将该节点的左子节点入队(如果有的话)。 d. 将该节点的右子节点入队(如果有的话)。 这样,通过不断出队和入队的操作,就可以按照从上到下、从左到右的顺序遍历整个二叉树的节点。需要注意的是,广度优先遍历不需要使用递归,而是利用队列来实现节点的访问顺序。 代码实现的话,可以使用Python的collections模块的deque双端队列来实现队列的功能。具体代码如下: ``` from collections import deque def breadth_first_traversal(root): if root is None: return queue = deque() queue.append(root) while queue: node = queue.popleft() # 访问节点 print(node.value) if node.left is not None: queue.append(node.left) if node.right is not None: queue.append(node.right) ``` 以上是广度优先遍历二叉树的方法和代码实现。通过使用队列,可以按照层次遍历的方式遍历二叉树的节点。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python算法系列—深度优先遍历算法【二叉树】](https://download.csdn.net/download/weixin_38715879/13745057)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [python实现二叉树的广度优先遍历和深度优先遍历](https://blog.csdn.net/qq_22337119/article/details/103480219)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值