【问题标题】:Binary Tree Balanced Check Using recursion?使用递归的二叉树平衡检查?
【发布时间】:2017-01-09 22:31:33
【问题描述】:

大家好,我想了解如何查看二叉树是否平衡。我试图打印出 cout 语句以尝试进一步理解它,但没有运气。

算法思想是如果返回-1不平衡,如果返回任何其他值则平衡。

但是我并不真正了解该算法的工作原理。 但我想知道的一些事情是;

int checkBalance(node *root)
{
if (root == NULL) return 0;

int left = checkBalance(root->left);
int right = checkBalance(root->right);
 //cout << "Root: " << root->key << " Left: " << left << ", Right: " << right << endl;

if (left == -1 || right == -1) return -1;
if (abs(left-right) > 1) return -1;

if (left > right) return left+1;
return right+1;
}

我的困惑在于以下代码行:

  1. 如果(根== NULL)返回0;
    • 当它返回 0 时会发生什么,什么时候达到 0?是为了防止递归一直到未知的内存地址,还是返回数字0有什么意义?
  2. 如果(左>右)返回左+1;

    • 为什么左边比右边大?当我查看它时,它总是返回右+1,因为条件永远不会为真,所以没有任何增量“左”?
  3. int left = checkBalance(root->left);

    • 以这种方式声明 int 是什么意思?这是让左>右的东西吗?

感谢您抽出宝贵时间阅读,我已经尝试自己研究这个问题,但我很难理解这段代码是如何工作的。

完整代码:http://pastebin.com/raw/VaiUNVdJ(案例6检查,案例1添加节点)

【问题讨论】:

  • 您似乎对这个算法的工作方式有一些误解。有一些条件可以定义什么是平衡二叉树。这些是您在算法的每个步骤中检查的条件。你应该阅读this post
  • 是的,我确实有一些误解,我明天会尝试再次阅读该帖子。我个人觉得递归有点难以理解有时真正发生的事情。但我会尽力研究链接,谢谢!
  • 要理解递归,你应该练习一些基本的算法,并在 Visual Studio 等 IDE 中逐行运行它们。这样,您就可以看到每个递归调用在调用堆栈上的内存。随着时间的推移,你应该会变得更好。

标签: c++ recursion tree binary-tree


【解决方案1】:

这是基本的 BBT 检查。它检查子树是否平衡。如果不是,则返回 -1;如果是,则返回深度。

在伪代码中:

  • 如果给定的子树为空,则返回 0(深度)
  • 在左右子树上递归(检查平衡和深度)
  • 如果任一子树不平衡,则返回 -1
  • 比较左右深度;如果它们相差超过 1,则返回 -1
  • 如果我们到达这里,这个子树是平衡的。返回它的深度。这是两个子树深度中较大的一个,加上 1。

解决您的具体问题:

  1. 此算法返回树深度(如果不平衡,则返回-1)。空树的深度为 0。
  2. 只要左树比右树深,左树就比右树大。看到这个还有问题吗?
  3. 这是您声明和初始化变量的方式。它与 in left = 0 的语法相同,只是赋值的 RHS 是一个表达式。

这是否足以让你摆脱困境?


让我们采用您提供的节点值,使用以 49 为根、子节点为 48 和 51 的树结构,中缀表示法可能如下所示:

(48, 49, (50, 51, 52))

更严格的形式,

49->left  = 48
49->right = 51
51->left  = 50
51->right = 52
There are no other children

以 root = 节点 49 开头,我们得到

int left = checkBalance(root->left);    // returns depth of 1
int right = checkBalance(root->right);  // returns depth of 2

现在,left ,所以最后的比较返回right+1,或者3,这是正确的树深度。

【讨论】:

  • 感谢您的回复! 1. 好的,现在明白了。 2/3。怎么样?我的想法是 int left = checkBalance(root->left);表示'left'指的是root->left的内存地址?在我看来,这意味着您然后比较左侧的“内存地址”是否大于右侧的“内存地址”(左>右)引导我向右:)
  • 不! checkBalance 返回树的深度,而不是对象的内存地址!
  • 还有,谁说左子树的内存比右子低?这些东西都是从堆里出来的。
  • 回复 1:哦,是的。真的!但我仍然不明白会发生什么;让我们说; 48、49、50、51、52个节点要简化?但是在哪个阶段左>右?代码如何知道这一点?正如你所说的 checkBalance 返回树的深度,但我不太确定这是怎么发生的。我很困惑,对不起。回复2:是的,比较内存地址没有意义,我只是想指出,我真的没有得到那部分,这是我能理解的最接近的部分!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多