【数据结构】二叉树的层序遍历(BFS)


当我们面对一个树结构时,常常需要对其进行遍历以获取其中的节点信息。其中一种常用的遍历方式是层序遍历,也称为广度优先搜索(BFS)。本篇博客将详细介绍层序遍历的原理和实现方法。

1.层序遍历的原理

层序遍历以树的根节点开始,按照从上到下、从左到右的顺序逐层遍历树中的节点。这意味着在遍历当前层的节点之前,需要先遍历完上一层的节点。层序遍历基于队列的数据结构实现,它的过程可以描述如下:

1.1.创建一个队列,并将根节点入队。

1.2.当队列不为空时,执行以下步骤:

  • 从队列中取出一个节点,访问该节点。
  • 将该节点的所有子节点(如果存在)依次入队。

1.3如果队列为空,则表示遍历结束。

由于队列的特性,首先入队的节点会先被访问,保证了按照层级顺序遍历节点。

2.层序遍历的实现

      1
     / \
    2   3
   / \   \
  4   5   6

首先,我们创建一个空队列,并将根节点1入队。然后按照队列非空的条件,执行以下步骤:

  1. 取出队列中的第一个节点1,并访问它。
  2. 将节点1的子节点2和3依次入队。
  3. 队列变为[2, 3]。
  4. 取出队列中的第一个节点2,并访问它。
  5. 将节点2的子节点4和5依次入队。
  6. 队列变为[3, 4, 5]。
  7. 取出队列中的第一个节点3,并访问它。
  8. 将节点3的子节点6入队。
  9. 队列变为[4, 5, 6]。
  10. 取出队列中的第一个节点4,并访问它。此时该节点没有子节点入队。
  11. 队列变为[5, 6]。
  12. 取出队列中的第一个节点5,并访问它。此时该节点没有子节点入队。
  13. 队列变为[6]。
  14. 取出队列中的第一个节点6,并访问它。此时该节点没有子节点入队。
  15. 队列为空,遍历结束。

按照上述步骤,我们可以得到层序遍历的结果为:[1, 2, 3, 4, 5, 6]。

void BinaryTreeLevelOrder(BTNode* root)
{
	// 定义一个队列
	Queue q;
	QueueInit(&q);  // 初始化队列

	if (root != NULL)  // 如果根节点不为空,将其入队
		QueuePush(&q, root);

	while (!isEmptyQueue(&q))  // 当队列不为空时循环
	{
		// 取出队头元素
		BTNode* front = QueueFront(&q);
		printf("%c ", front->_data);  // 输出该节点的值

		// 如果该节点有左子节点,将其加入队列
		if (front->_left != NULL)
			QueuePush(&q, front->_left);

		// 如果该节点有右子节点,将其加入队列
		if (front->_right != NULL)
			QueuePush(&q, front->_right);

		QueuePop(&q);  // 出队队头元素
	}

	printf("\n");
	QueueDestroy(&q);  // 销毁队列
}

在这里插入图片描述

3.层序遍历的应用

层序遍历在树的分析和处理中有广泛的应用。以下是一些常见的应用场景:

  1. 获取树的层级信息:层序遍历可以按照层级将树的节点进行分组,方便进行树的层级分析。
  2. 寻找最短路径:在树或图中,层序遍历可以用于寻找最短路径,因为它先遍历完当前层的节点,再遍历下一层的节点,从而保证了寻找最短路径的准确性。
  3. 构建二叉树:层序遍历可以根据给定的节点值列表,按照从上到下、从左到右的顺序构建二叉树。

除了以上应用,层序遍历还可以用于树的序列化和反序列化、树的复制等操作。
用层序遍历判断是不是

层序遍历实现判断二叉树是否为完全二叉树

完全二叉树:在二叉树中,如果除了最后一层外,其它层的节点数都达到最大值,并且最后一层的节点都靠左排列,那么这棵二叉树就是完全二叉树。完全二叉树在实际应用中有着广泛的应用,因此判断一棵二叉树是否为完全二叉树是一个常见的问题。

层序遍历实现判断完全二叉树的思路:

层序遍历是一种按照从上到下、从左到右的顺序访问二叉树节点的方法。通过层序遍历,我们可以逐层遍历二叉树的节点,并在遍历过程中进行判断,从而确定二叉树是否为完全二叉树。

具体实现步骤如下:

  1. 首先,将二叉树的根节点入队。

  2. 开始循环,直到队列为空。

  3. 在每次循环中,取出队列的首个节点。

  4. 当取出的节点为空时,停止入队操作。

  5. 如果在上一步中发现了空节点,那么此时应该检查队列中是否还有非空节点。如果有非空节点,则说明该二叉树不是完全二叉树。

  6. 继续循环,将当前节点的左右子节点入队。

  7. 最后,在循环结束后,再次检查队列中是否还有非空节点。

  8. 如果有非空节点,则说明该二叉树不是完全二叉树。

    如果队列中没有非空节点,则说明该二叉树是完全二叉树。

bool isBinaryTreeComplete(BTNode* root)
{
    if (root == NULL)
    {
        return true;
    }

    BTNode* front = root;
    Queue q;
    QueueInit(&q);
    if (front != NULL)
        QueuePush(&q, front);

    while (!isEmptyQueue(&q))
    {
        front = QueueFront(&q);

        if (front == NULL)
        {
            // 如果取出的节点为空,则停止入队操作,开始检查队列中是否还有非空节点
            break;
        }

        // 将当前节点的左右子节点入队
        QueuePush(&q, front->_left);
        QueuePush(&q, front->_right);
        QueuePop(&q);
    }

    while (!isEmptyQueue(&q))
    {
        // 循环结束后,检查队列中是否还有非空节点
        front = QueueFront(&q);
        QueuePop(&q);

        if (front != NULL)
        {
            // 如果存在非空节点,则说明该二叉树不是完全二叉树
            QueueDestroy(&q);
            return false;
        }
    }
    QueueDestroy(&q);
    return true;
}

总结

层序遍历是一种广度优先搜索的遍历方式,适用于树结构。通过利用队列实现层序遍历,我们可以按照从上到下、从左到右的顺序逐层遍历树中的节点。层序遍历广泛应用于树的分析、最短路径寻找、二叉树的构建等场景。掌握层序遍历的原理和实现方法将对解决相关问题非常有帮助。

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
叉树的层序遍历是一种按照从上到下、从左到右的顺序访问二叉树节点的方法。通过层序遍历,我们可以逐层遍历二叉树的节点,并在遍历过程中进行判断,从而确定二叉树是否为完全二叉树层序遍历是一种广度优先搜索的遍历方式,适用于树结构。通过利用队列实现层序遍历,我们可以按照从上到下、从左到右的顺序逐层遍历树中的节点。具体实现方法如下: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def levelOrder(root: TreeNode) -> List[List[int]]: if not root: return [] res = [] queue = [root] while queue: level = [] for i in range(len(queue)): node = queue.pop(0) level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) res.append(level) return res ``` 以上代码中,我们定义了一个`TreeNode`类来表示二叉树的节点,`levelOrder`函数用于实现二叉树层序遍历。在函数中,我们首先判断根节点是否为空,如果为空则直接返回空列表。然后定义一个`res`列表来存储遍历结果,定义一个`queue`队列来存储待遍历的节点。接下来,我们使用一个`while`循环来遍历整个二叉树。在每一层遍历中,我们定义一个`level`列表来存储当前层的节点值,然后使用一个`for`循环来遍历当前层的所有节点。在循环中,我们首先弹出队列中的第一个节点,并将其值加入到`level`列表中。然后判断该节点是否有左右子节点,如果有则将其左右子节点加入到队列中。最后将`level`列表加入到`res`列表中,表示当前层的遍历已经完成。最终返回`res`列表即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q_hd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值