1

这是节点定义:

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

4 回答 4

6

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

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

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

  • 你为什么要取root的地址?
  • 为什么不测试第一个左指针是否为空?
  • 您可以简单地使用 std::map,但学习如何实现二叉树也是一个好主意。
于 2009-08-23T19:26:25.863 回答
5

这是对问题的错误解决方案。Neil Butterworth 已经在您的代码上注明,我将在算法上注明。

您的算法只检查一个非常具体的情况 - 孙节点是否指向其祖父母。您应该做的是在到达节点的过程中收集父节点,并查看节点的子节点不是其父节点之一。

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

于 2009-08-23T19:36:17.247 回答
1

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

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

笔记:

  • 数组将是存储节点的好方法。如果您要避免 STL(好奇:为什么?),那么您将不得不管理自己的内存。可行,但要重新发明它是一个脆弱的轮子。
  • 获取数组大小的 for 循环检查将不起作用;如果你使用 malloc/free 或 new/delete 那么你必须事先指定你想要的数组的大小;您应该使用该大小而不是每次通过 for 循环都计算它。
  • 递归算法的典型模式是具有“外部”和“内部”功能。外层函数是由外部代码调用的,做初始设置等。内层函数只被外层函数调用,往往有更复杂的参数集(取外层函数设置的数据),调用自己来执行实际的递归。
  • 您将需要两个数组:一个用于您已访问的节点列表,另一个用于您尚未访问的节点列表。
于 2009-08-23T20:21:26.500 回答
-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);
}
于 2009-08-23T19:44:42.347 回答