这是节点定义:
struct node{
int data;
stuct node * left;
struct node * right;
};
我要做的是列出指向祖先节点的所有节点。在发布错误的解决方案并从答案中获取建议后,我的新解决方案是:
递归遍历二叉树。将当前节点添加到节点数组,然后检查当前节点的子节点是否指向任何先前的祖先节点。
默认情况是节点为NULL。如果发生这种情况,函数将返回。
应该如何运作:
将节点添加到数组
检查左子项是否为NULL。
如果没有,它会将子节点与之前的每个节点进行比较。
如果发现故障,则报告。
如果没有,它会以子项为参数调用该函数。
重复直至完成。 (二叉树的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;
}
答案 0 :(得分:6)
我不知道递归,但是这个:
if (&root->left->left == &root){
在我可以描述的更多方面是错误的,但无论如何这里有三个问题:
答案 1 :(得分:5)
这是解决问题的错误方法。 Neil Butterworth已经注意到你的代码,我会注意到算法。
您的算法仅检查一个非常具体的案例 - 孙子节点是否指向其祖父母。你应该做的是在一个节点的路上收集父母,看看节点的孩子不是它的父母之一。
有很多方法可以做到这一点。一种是在节点结构中添加一个计数器,并在开始遍历树之前将所有节点的计数器设置为零。每当到达节点时,确保计数器为零,然后将其增加1。这意味着如果您看到一个计数器不为零的孩子,您已经访问过它,因此该树无效。
答案 2 :(得分:1)
完成这种检查的另一种方法是对节点进行广度优先扫描,同时保留已经访问过的节点向量(可以按地址对其进行排序)。每次访问节点时,断言它不在向量中,然后将其添加到适当的位置以保持已访问列表的排序。
这种检查的优点是可以在不修改树或节点结构本身的情况下执行,但是会有一点性能损失。
注意:
答案 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);
}