使用图遍历来测试图是不是是完美二叉树

Posted

技术标签:

【中文标题】使用图遍历来测试图是不是是完美二叉树【英文标题】:Using graph traversal to test is a graph is a perfect binary tree使用图遍历来测试图是否是完美二叉树 【发布时间】:2021-12-30 08:07:04 【问题描述】:

当给定一个由邻接表表示的无向图 G 时,如何使用 DFS 来查看该图是否是完美二叉树?

我已经能够识别边缘情况:例如,对于深度 D,您需要 2^n-1 个节点,您可以使用对数计算出最大深度,如果不完整,您知道您没有完美的树,但我想不出使用邻接表和 DFS 进行测试的有效方法。

【问题讨论】:

您可以有一个计数器字典,您可以在其中跟踪每个级别中的节点数。还有一组跟踪访问过的节点。当您这样做时,您的 dfs 会跟踪深度并将新节点添加到它们各自的级别。最后,检查每个级别是否有适当数量的节点。 最难的部分是找出哪个节点是这棵完美二叉树的根。如果你有一个图,它是图意义上的树,那么你可以选择任何节点作为根,你会得到一个父子意义上的树。但在你的情况下,只有一个可能的根会产生一棵完美的二叉树。 我建议一个算法分为两部分:首先,识别一个候选根;然后,检查这个根,你有一个完美的二叉树。 PS:对于以后的问题,请考虑在the computer science stackexchange 上提问,而不是在 *** 上提问。对于更多的理论问题,您可能会在此处获得更好的答案,而对于更多面向编程的问题,您可能会在此处获得更好的答案。 @Stef 根是唯一度数为 2 的顶点 【参考方案1】:

在一棵不为空的完美二叉树中,有?个节点,我们有以下属性:

节点数 ? 小于 2 的幂,即 ℎ=log2(?+1) 是整数。 ?=2−1 边数为?−1 没有超过 3 个邻居的节点。 当 ? > 1 时,(只有)一个节点正好有 2 个邻居:它是根。 当 ? > 1 时,树的叶子只有一个邻居:有 2ℎ-1。 根与叶之间的距离为ℎ−1。

这些属性可以一个接一个地检查。一旦确定了根,就可以执行遍历来检查距离属性。使用 DFS 或 BFS。

【讨论】:

如果你已经确定了根并且要进行遍历,那么只有属性“深度 是的,但是像边数这样的检查是值得的,因为它非常便宜,并且可以在不进行遍历甚至构建邻接列表的情况下快速退出。此外,在构建邻接列表时可以检查超过 3 个邻居,从而更快地退出。【参考方案2】:

如果图是空的,或者只有一个顶点,则返回true。

否则,请检查以确保图形是连通的且非循环的。

那么,如果它是一棵完美的二叉树,那么它必须只有一个度数为 2 的顶点。这就是根。让ab 成为它的两个孩子。那么:

let depthA = depthIfPerfect(a, root);
let depthB = depthIfPerfect(b, root);
return depthA == depthB && depthA >=0

地点:

depthIfPerfect(node, parent):

    if degree(node) == 1:
        return 1;
    if degree(node) != 3:
        return -1; //not perfect

    let a and b be the neighbors that aren't parent

    let depthA = depthIfPerfect(a, node);
    let depthB = depthIfPerfect(b, node);
    
    if (depthA != depthB || depthA < 0):
        return -1: //not perfect
    return depthA+1;

如果你愿意,你可以在这个遍历中混合检查连通性和非循环性。

【讨论】:

以上是关于使用图遍历来测试图是不是是完美二叉树的主要内容,如果未能解决你的问题,请参考以下文章

树二叉树满二叉树完全二叉树

树二叉树完全/满/平衡二叉树的理解与对比

3 分钟理解完全二叉树平衡二叉树二叉查找树

算法漫游指北(第十三篇):二叉树的基本概念满二叉树完全二叉树二叉树性质二叉搜索树二叉树定义二叉树的广度优先遍历

二叉树 详解

二叉树及特殊二叉树(满二叉树完全二叉树二叉排序树平衡二叉树)的定义和性质(附详细推理过程)