树的迭代遍历

本文介绍了树的深度优先遍历(DFS)和广度优先遍历(BFS)的迭代实现。对于DFS,通过双色标记法,使用栈进行前序、中序和后序遍历。BFS则利用双端队列进行,适用于查找最短路径或特定距离的目标节点。提供了Python代码示例来展示这两种遍历方法。
摘要由CSDN通过智能技术生成

树的迭代遍历

深度优先遍历(Depth-First-Search,DFS),沿着树的深度遍历树的节点,尽可能深的搜索树的分支。前序遍历和后序遍历是最常见的两种 DFS 方式,而 中序遍历一般用于平衡二叉树。
树的DFS的迭代方式实现,使用的数据结构是栈,配合双色标记法可以完成三种遍历方式的代码实现。下面以中序遍历实现为例:

实现思路:

  • 使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。
  • 如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。
  • 如果遇到的节点为灰色,则将节点的值输出。

注:如要实现前序、后序遍历,也只需要调整左右子节点的入栈顺序即可,其他部分是无需做任何变化。

代码实现:

import collections

class TreeNode(object):
    """
    定义树的节点
    """
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

def dfs_in_order_traversal(root: TreeNode):
    """
    树的深度优先遍历(以下简称 DFS)迭代方法实现(双色标记发)
    :param root: 树的根节点
    :return: 遍历结果
    """
    # 以下代码以中序遍历为例,改变压栈顺序则相应为前、中、后序树的遍历
    # 使用颜色标记节点的状态,白色表示未访问,灰色表示已访问
    WHITE, GRAY = 0, 1
    # 遍历结果存储列表
    res = []
    stack = [(WHITE, root)]
    while stack:
        color, node = stack.pop()
        if node is None:
            continue
        # 如果遇到白色节点,则将其标记为灰色
        # 然后将其右子节点、自身、左子节点依次压入栈中
        # 注意改变压入栈的顺序则变为前序、后序遍历
        if color is WHITE:
            stack.append((WHITE, node.right))
            stack.append((GRAY, node))
            stack.append((WHITE, node.left))
        else:
            res.append(node.val)

    return res

广度优先遍历(BFS)采用横向搜索的方式,BFS 比较适合解决最短距离/路径某一个距离的目标的这样的问题。

实现思路:

  1. 首先将根节点放入队列中。
  2. 从队列中取出第一个节点,并检验它是否为目标:
    如果找到目标,则结束搜索并回传结果。
    否则将它所有尚未检验过的直接子节点加入队列中。
  3. 若队列为空,表示整张图都检查过了——亦即图中没有欲搜索的目标。结束搜索并回传“找不到目标”。
  4. 重复步骤 2。

代码实现:

import collections

class TreeNode(object):
    """
    定义树的节点
    """
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
def bfs_tree_traversal(root: TreeNode, k):
    """
    使用双端队列操作树的广度优先搜索(BFS)
    双端队列限制一头出队、入队则变成栈,限制一头只出队,另一个头只入队,则变成普通队列
    bfs适合用来查找最短距离或路径、距离某一个目标的长度
    数组删除元素的时间复杂度是O(N)
    k是满足条件的距离长度,大于或小于k也是用这个模板的代码
    """
    # 双端队列(两边都可以插入和删除)位于collections包下
    # deque默认右端是队尾,左端是队头
    # 默认方法是右端,即队尾
    queue = collections.deque([root])
    
    # 记录层数,即标记层
    step = 0
    # 满足条件需要返回的节点存储在列表中
    ans = []
    
    while queue:
        # 当前层节点个数就是队列的长度
        size = len(deque)
        # 遍历当前层的所有节点
        for _ in range(size):
            # 数据出队操作,左侧是队头
            node = queue.popleft()
            # 判断是否满足条件
            if (step == k):
                ans.append(node)
            # 检查当前节点它的下一层子节点,如果存在插入队列中
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        # 遍历完当前层的节点后,记录层的标记step自增1
        step += 1
    
    # 返回结果
    return ans

参考文献:
https://leetcode-solution-leetcode-pp.gitbook.io/leetcode-solution/thinkings/tree#shu-de-bian-li-die-dai-xie-fa

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值