二叉树节点故障

时间:2009-08-23 19:23:06

标签: c++ c binary-tree

这是节点定义:

struct node{
    int data;
    stuct node * left;
    struct node * right;
};

我要做的是列出指向祖先节点的所有节点。在发布错误的解决方案并从答案中获取建议后,我的新解决方案是:

递归遍历二叉树。将当前节点添加到节点数组,然后检查当前节点的子节点是否指向任何先前的祖先节点。

默认情况是节点为NULL。如果发生这种情况,函数将返回。

应该如何运作:

将节点添加到数组

检查左子项是否为NULL。

如果没有,它会将子节点与之前的每个节点进行比较。

如果发现故障,则报告。

如果没有,它会以子项为参数调用该函数。

重复直至完成。 (二叉树的rhs也一样)

问题:

  • 数组是存储的最佳选择 节点?
  • 这有用吗? for(i = 0; i< sizeof(arrOfNodes)/ sizeof(node); i ++)
  • 因为函数是递归的, 数组和数组索引不能 在函数内初始化 (或者他们可以吗?)他们应该如此 全球?
  • 拥有两个阵列会更好吗? (一个用于LHS,一个用于 RHS)

代码:

void findFault(node * root){
    if (root == NULL){
      return;
    }

    arrOfNodes[index++] == root; // array of nodes

    if (root->left != NULL){
      for (i = 0; i < sizeof(arrOfNodes) / sizeof(node); i++){
         if (ar[i] == root->left){
             printf("%d", root->left);
             return;
         }
       }
       findFault(root->left);
    } else return;

    if (root->right != NULL){
      for (i = 0; i < sizeof(ar) / sizeof(node); i++){
         if (ar[i] == root->right){
             printf("%d", root->right);
             return;
         }
      }
      findFault(root->right);
    } else return;
}

4 个答案:

答案 0 :(得分:6)

我不知道递归,但是这个:

if (&root->left->left == &root){

在我可以描述的更多方面是错误的,但无论如何这里有三个问题:

  • 你为什么要取根的地址?
  • 为什么不测试第一个左指针是否为空?
  • 您可以简单地使用std :: map,但学习如何实现二叉树也是一个好主意。

答案 1 :(得分:5)

这是解决问题的错误方法。 Neil Butterworth已经注意到你的代码,我会注意到算法。

您的算法仅检查一个非常具体的案例 - 孙子节点是否指向其祖父母。你应该做的是在一个节点的路上收集父母,看看节点的孩子不是它的父母之一。

有很多方法可以做到这一点。一种是在节点结构中添加一个计数器,并在开始遍历树之前将所有节点的计数器设置为零。每当到达节点时,确保计数器为零,然后将其增加1。这意味着如果您看到一个计数器不为零的孩子,您已经访问过它,因此该树无效。

答案 2 :(得分:1)

完成这种检查的另一种方法是对节点进行广度优先扫描,同时保留已经访问过的节点向量(可以按地址对其进行排序)。每次访问节点时,断言它不在向量中,然后将其添加到适当的位置以保持已访问列表的排序。

这种检查的优点是可以在不修改树或节点结构本身的情况下执行,但是会有一点性能损失。

注意:

  • 数组是存储节点的好方法。如果你正在避免STL(好奇:为什么?)那么你将不得不管理自己的记忆。可行,但这是重塑的一个脆弱的轮子。
  • 您的for循环检查以获取数组的大小将不起作用;如果您使用malloc / free或new / delete,那么您必须事先指定所需数组的大小;你应该使用那个大小,而不是每次通过for循环计算它。
  • 递归算法的典型模式是具有“外部”和“内部”功能。外部函数是由外部代码调用的函数,并进行初始设置等。内部函数仅由outser函数调用,往往具有更复杂的参数集(由外部函数设置数据),以及调用本身就是为了执行实际的递归。
  • 您将需要两个阵列:一个用于您访问过的节点列表,另一个用于您尚未访问的节点列表。

答案 3 :(得分:-1)

我不知道生成二叉树的算法是否能够传播节点左/右孩子以外的故障。

无论如何,这是您的代码的更正版本:

void findFault(node * root){
    if (root == NULL){
      return;
    }

    if (root->left == root){
      printf("left: %d", root->data);
    } else findFault(root->left);

    if (root->right == root){
      printf("right: %d", root->data);
    } else findFault(root->right);
}