简体   繁体   English

二叉树节点故障

[英]Binary Tree Node Fault

Here's the node definition: 这是节点定义:

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

What I am trying to do is list all the nodes that point to an ancestor node. 我想要做的是列出所有指向祖先节点的节点。 After posting the wrong solution and taking advice from the answers, my new solution is: 发布错误的解决方案并从答案中获取建议后,我的新解决方案是:

Recursively go through the binary tree. 递归地遍历二叉树。 Add the current node to an array of nodes and then check if the children of the current node point to any of the previous ancestor nodes. 将当前节点添加到节点数组中,然后检查当前节点的子节点是否指向任何先前的祖先节点。

The default case is the node being NULL. 默认情况是节点为NULL。 If that happens the function returns. 如果发生这种情况,函数将返回。

How it is supposed to work: 应该如何工作:

Adds the node to the array 将节点添加到数组

Checks if the left child is NULL. 检查左孩子是否为NULL。

If not, it compares the child to each of the previous nodes. 如果不是,它将子节点与每个先前节点进行比较。

If it finds a fault, it reports it. 如果发现故障,则报告它。

If not, it calls the function with the child as the argument. 如果不是,它将以子代为参数调用该函数。

Repeat until finished. 重复直到完成。 (Does same for rhs of binary tree) (对于二叉树的rhs相同)

Questions: 问题:

  • Is an array the best thing to store the nodes? 数组是存储节点的最好方法吗?
  • Does this work? 这样行吗? for (i = 0; i < sizeof(arrOfNodes) / sizeof(node); i++) 对于(i = 0; i <sizeof(arrOfNodes)/ sizeof(node); i ++)
  • Because the function is recursive, the array and the array index can't be initialized inside the function (or can they be?) so should they be global? 由于该函数是递归的,因此无法在函数内部初始化数组和数组索引(或者它们可以是吗?),因此它们应该是全局的吗?
  • Would it be better to have two arrays? 拥有两个数组会更好吗? (one for the LHS and one for the RHS) (一个用于LHS,一个用于RHS)

The code: 编码:

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

I don't know about recursion, but this: 我不知道递归,但这:

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

is wrong in more ways that I can possibly describe, but anyway here are three issues: 我可能会描述的更多方式是错误的,但是无论如何,这是三个问题:

  • Why are you taking the address of root? 为什么要使用root的地址?
  • Why don't you test that the first left pointer is null? 为什么不测试第一个左指针为空?
  • You could simply use a std::map, but learning how to implement a binary tree is a good idea too. 您可以简单地使用std :: map,但是学习如何实现二叉树也是一个好主意。

This is an incorrect solution to the problem. 这是对该问题的错误解决方案。 Neil Butterworth already noted on your code, I'll note on the algorithm. 尼尔·巴特沃思(Neil Butterworth)已经在您的代码中指出了,我将在算法中指出。

Your algorithm only checks a very specific case - whether a grandchild node points to its grandparent. 您的算法仅检查非常特殊的情况-孙子节点是否指向其祖父母。 What you should do is collect the parents along the way to a node and see that a node's child isn't one of its parents. 您应该做的是沿途收集节点的父母,并查看节点的孩子不是其父母之一。

There are many ways to do this. 有很多方法可以做到这一点。 One is to add a counter to your node struct and set all nodes' counters to zero before you begin traversing the tree. 一种方法是在您的节点结构上添加一个计数器,并在开始遍历树之前将所有节点的计数器设置为零。 Whenever you reach a node you make sure the counter is zero and then increase it by one. 每当到达节点时,请确保计数器为零,然后将其增加一。 This means that if you see a child whose counter isn't zero, you've already visited it and therefore the tree isn't valid. 这意味着,如果您看到一个计数器不为零的孩子,那么您已经访问过它,因此该树无效。

Another way to accomplish this kind of check is to do a breadth-first sweep of the nodes, all the while keeping a vector of nodes you have visited already (which you can keep sorted by address). 完成这种检查的另一种方法是对节点进行广度优先扫描,同时始终保持已访问过的节点向量(您可以按地址对它进行排序)。 Each time you visit a node, assert it is not in the vector, then add it to the appropriate place to keep the visited list sorted. 每次访问节点时,都断言它不在向量中,然后将其添加到适当的位置以使访问列表保持排序。

The advantage to this kind of check is it can be performed without modifying the tree or node struct itself, though there is a bit of a performance penalty. 这种检查的优点是,尽管有一些性能损失,但它可以在不修改树或节点结构本身的情况下执行。

Notes: 笔记:

  • An array would be a fine way to store the nodes. 数组是存储节点的好方法。 If you're avoiding STL (curious: why?) then you'll have to manage your own memory. 如果要避免使用STL(好奇:为什么?),则必须管理自己的内存。 Doable, but it's a brittle wheel to reinvent. 可行,但这是重塑的脆弱之轮。
  • Your for loop check to get the size of the arrays will not work; 您进行的for循环检查以获取数组的大小将不起作用; if you use malloc/free or new/delete then you'll have to specify the size of the array you want beforehand; 如果使用malloc / free或new / delete,则必须事先指定所需的数组大小; you should use that size instead of calculating it every time through the for loop. 您应该使用该大小,而不是每次通过for循环都进行计算。
  • The typical pattern for a recursive algorithm is to have an "outer" and "inner" function. 递归算法的典型模式是具有“外部”和“内部”功能。 The outer function is the one called by external code and does the initial setup, etc. The inner function is only called by the outser function, tends to have a more complicated parameter set (taking data set up by the outer function), and calls itself to perform the actual recursion. 外部函数是由外部代码调用并执行初始设置的函数。内部函数仅由outser函数调用,往往具有更复杂的参数集(通过外部函数设置数据),并调用本身执行实际的递归。
  • You will need two arrays: one for the list of nodes you have visited, and one for the list of nodes you have yet to visit. 您将需要两个数组:一个数组用于访问的节点列表,另一个数组用于尚未访问的节点列表。

I don't know if the algorithm that generates the binary tree is able to propagate a fault other than node's left/right child. 我不知道生成二叉树的算法是否能够传播节点左/右子节点以外的故障。

Anyway, this is a corrected version for your code: 无论如何,这是您的代码的更正版本:

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