繁体   English   中英

二叉树节点故障

[英]Binary Tree Node Fault

这是节点定义:

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

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

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

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

应该如何工作:

将节点添加到数组

检查左孩子是否为NULL。

如果不是,它将子节点与每个先前节点进行比较。

如果发现故障,则报告它。

如果不是,它将以子代为参数调用该函数。

重复直到完成。 (对于二叉树的rhs相同)

问题:

  • 数组是存储节点的最好方法吗?
  • 这样行吗? 对于(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;
}

我不知道递归,但这:

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

我可能会描述的更多方式是错误的,但是无论如何,这是三个问题:

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

这是对该问题的错误解决方案。 尼尔·巴特沃思(Neil Butterworth)已经在您的代码中指出了,我将在算法中指出。

您的算法仅检查非常特殊的情况-孙子节点是否指向其祖父母。 您应该做的是沿途收集节点的父母,并查看节点的孩子不是其父母之一。

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

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

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

笔记:

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

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

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

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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM