C++ 中的二叉树剪枝2025年5月15日 | 阅读12分钟 引言二叉树是一种分层数据结构,由节点组成,每个节点最多有两个子节点:节点必须有一个左子节点和一个右子节点。由于其在表示分层关系方面的卓越性,二叉树是当今计算机科学中最常用的数据结构之一。二叉树中的每个节点都有一个值,并且一个节点被定义为根节点,同时有两个子分支,一个左分支和一个右分支。
二叉树中剪枝的概念基于定义,二叉树中的剪枝可以操作性地定义为在具有某些特征后规则性地删除某些子树。在涉及二叉树的计算问题中,通常使用剪枝来通过删除与当前问题不相关的分支来简化树。当解决具有大量重复数据或分支的树的问题时,它特别有用,这些分支在确定问题的解决方案方面没有用处。
用于剪枝的递归树遍历使用递归树遍历可以简单地解决二叉树剪枝问题。分而治之的方法利用了二叉树的这个属性,因为每个节点都可以再次看作是某个子树的根节点。这种递归结构使我们能够在每个节点上执行剪枝操作,通过首先在子节点上解决问题来实现递归。 在进行剪枝的二叉树遍历中,常用的方法是后序遍历。在后序遍历中,在遍历节点之前,先遍历节点的左子树和右子树。这在剪枝中特别有用,因为它意味着只有在所有子节点都已被剪枝后,才会做出剪枝节点的决定。换句话说,从决策树的底部开始,任何剪枝都包含有关被询问节点所代表的树的完整信息。 用于二叉树剪枝的后序遍历算法如下:
这确保了剪枝是基于从每个被评估的节点开始的子树的状态进行的,并且是其他节点的前提。由于后序遍历在处理父节点之前先处理两个子节点,因此该算法可以删除不必要的子树。 例如,在剪枝值为 0 和 1 的二叉树的决策树情况下,该技术将首先应用于当前节点的左子树和右子树。基本上,如果两个子树都被剪枝且当前节点的值为 0,则剪枝该节点。事实上,如果节点的值为 1 或其子节点未被剪枝,则会进一步保留该节点。这种方法保证了生成的树只包含输入树的重要部分;即包含 1 的节点或具有有意义子树的节点。 递归树遍历用于剪枝的时间复杂度为 O(n),其中 n 是树中的节点数,因为所有节点都只处理一次。至于空间复杂度,它等于 O(h),其中 h 是树的高度,因为存在递归栈。我们知道,平衡树的高度 h 是节点数的对数,这使得该算法在时间和空间上都最优。 后序遍历的理论依据后序遍历是二叉树剪枝中的一项重要策略,因为它能够在进行任何剪枝操作之前遍历整个子树。这种“自下而上”的方法至关重要,因为剪枝决策取决于节点子节点中包含的值。本质上,鉴于后序遍历在处理父节点之前从子节点开始,后序遍历能够在确定父节点的命运之前获取有关子节点的所有信息。
算法的属性根据以下重要的理论属性,二叉树剪枝算法可以被认为是高效实用的。这些属性包括:时间复杂度、空间复杂度以及算法对于各种二叉树结构的效率。 时间复杂度
空间复杂度
不同类型树的效率算法编程的理念是它能够处理各种类型的二叉树,包括有序、已排序或倾斜的二叉树。在平衡树中,避免了过度的递归结构,因此所需的时间和空间得到了优化。对于倾斜树,它可能需要更多的空间,但所需的时间仍然相当少,因为即使递归深度增加了,每个节点也只处理一次。 该剪枝算法在处理包含可能不同的节点值的树方面也很有效。对于某些节点包含 0 而其他节点包含 1 的树,该算法会剪除不重要的分支,同时保留重要的分支。由于我们只剪除选定的节点,因此可以保证生成的树只包含真正需要的作为树一部分的节点,这有助于节省内存的可消耗空间和用于对该树执行的任何进一步操作的最小计算能力。 边缘情况和注意事项在使用二叉树实现剪枝算法并分析结果时,应考虑算法执行期间可能出现的其他边缘情况。这些极端情况通常在具有非典型结构或节点值可能影响剪枝过程的树上遇到。处理这种情况可以使算法更全面,因为它能够接受各种形式的输入。 空树
单节点树
值为 0 的完整子树
编码输出剪枝前 这是原始树的中序遍历。这里显示的树的节点值为 0 和 1。 剪枝后 如果我们剪枝,我们会得到一棵只包含值为 1 的节点的树。这使得下面的结构更加浅显,因为所有只包含 0 的子树都已被消除。 剪枝后的二叉树结构正如我们所见,剪枝后只剩下有意义的节点。值为 1 的节点由于其重要性而被保留,而只包含 0 的子树则被剪枝。 |
在 C++ 中比较字符串时,开发人员经常需要在 std::string::compare() 函数和关系运算符 == 之间进行选择。虽然这两种方法的目标都是比较字符,但它们的行为和应用却有所不同。本文旨在阐明其中的差异……
阅读 4 分钟
在本文中,我们讨论了 C++ 中基于范围的 for 循环和基于迭代器的 for 循环之间的区别。在讨论它们之间的区别之前,我们必须了解 C++ 中的基于范围的 for 循环和基于迭代器的 for 循环及其语法、参数和示例。什么是基于范围的 for 循环...
阅读 6 分钟
在数论中,利赫雷尔数(Lychrel number)是指一个自然数,它通过反转其数字并将其加到原始数字上的重复过程,无法形成一个回文数。如果一个数永远无法成为回文数,那么它就是一个利赫雷尔数……
阅读 4 分钟
C++20 简介,标准库在并发和并行编程以及 std::execution 命名空间的支持方面取得了显著进展。此命名空间提供的最重要功能之一是 std::execution::read_env,这是一种访问...的方法。
阅读 6 分钟
在本文中,我们将通过几个例子讨论五面体数。什么是五面体数?五面体数由帕斯卡三角形的每一行的第五个数字表示,从至少包含五个数字的行开始。公式:以下是... 的公式。
阅读 4 分钟
问题描述:本问题中的起始基因字符串和结束基因字符串均为八个字符长,由“A”、“C”、“G”和“T”组成。此外,我们还有一个合法的基因突变库。一个基因必须存在于库中……
5 分钟阅读
在本文中,我们将讨论欧拉四平方恒等式及其在 C++ 中的实现。欧拉四平方恒等式是什么?根据欧拉四平方恒等式,每个正整数都可以写成四个完全平方数的和,有时也称为欧拉恒等式……
5 分钟阅读
20 是 C++ 标准库的另一个强大扩展,以及如何转换和处理范围的改进。它是 Ranges 库的一部分,Ranges 库是一种新的方法,它专注于以最优雅和最富有表现力的方式操作元素序列。
阅读 4 分钟
引言回文检查是一项常见的编程任务,正如我们在许多经常讨论的问题中已经看到的。然而,在这个工作的范围内,它们是必不可少的,因为它们是字符串级别上可标记的序列;回文是读起来相同的序列……
阅读 12 分钟
数学通常被描述为自然的通用语言,一个揭示支配我们周围世界的内在模式、结构和关系的系统。在无数令研究人员着迷的数学序列和构造中,帕多万序列以其优雅而脱颖而出...
阅读 15 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India