我在构建像这样的二叉树时遇到了麻烦:
view tree。
您会看到像-
这样的操作数节点只有一个孩子。
即使是像+-a
这样的简单树,代码也不起作用。
我的代码是:
// Represents a node of the required tree
typedef struct node { char data; struct node *left, *right; } node;
// Function to recursively build the expression tree
char* add(node** p, char* a)
{
// If its the end of the expression
if (*a == '\0')
return '\0';
while (1) {
char* q = "null";
if (*p == NULL) {
// Create a node with *a as the data and
// both the children set to null
node* nn = (node*)malloc(sizeof(node));
nn->data = *a;
nn->left = NULL;
nn->right = NULL;
*p = nn;
}
else {
// If the character is an operand
if (*a >= 'a' && *a <= 'z') {
return a;
}
// Build the left sub-tree
q = add(&(*p)->left, a + 1);
// Build the right sub-tree
q = add(&(*p)->right, q + 1);
return q;
}
}
}
int main()
{
node* s = NULL;
char a[] = "+-a";
add(&s, a);
return 0;
}
感谢您的帮助<3
答案 0 :(得分:-1)
摘要中有矛盾之处,并且没有意义。很难知道从哪里开始解释发生了什么。
我想一开始就是这不是应用递归的好地方。问题的一部分是固有的迭代:您想遍历字符串。将此与递归算法结合在一起显然会给您带来头痛,因为您根本做得不好。通常,递归是一个陷阱,在更干净的代码中进行迭代。 “需要”递归的数据结构也经常是陷阱。
无论如何,我最终都会提出一个可行的递归算法。现在,剖析您做错了什么。从add返回一个char指针将立即成为一个巨大的危险信号:使指针算法能够递归工作很困难,因为更改必须在整个调用堆栈中体现。从代码中消除这一点显然是一个开始。
接下来是while循环。循环本质上是一个迭代的事物,但是您将其包含在递归算法中:希望它的固有迭代性质已开始变得清晰。 while循环的原因也很愚蠢:使用if-else进行拆分是完全不必要的。正确的做法是简单地为每个调用分配一个新节点,而不必使用if,因为您永远不会照原样在已经存在的节点上进行递归,而且您绝对不需要else,因为无论是否需要递归逻辑,都需要发生是否必须分配一个新节点。因此,删除while循环和if-else。
接下来是q变量。我不知道您要使用它做什么,但是无论如何都是垃圾。已移除。分配新节点时的一个小要点是不需要新变量来分配新节点:您可以简单地使用* p。这样可以节省一行代码。
最后,我们介绍了递归逻辑。我已经讲过关于q的事情,因此无需赘述。这里的逻辑根本不起作用,因为您没有以适当的方式遍历字符串。同样,以递归算法执行此操作比以迭代方式编写要困难。
因此,这是实际工作的代码。我对压缩源采取了极大的自由态度,以便算法在垂直方向上占用较少的空间,因为节省LoC是一件好事。
int add(node** p, char* a, int i) {
if (a[i] == '\0') return i; // If end of expression
*p = (node*) malloc(sizeof(node));
(*p)->data = a[i];
(*p)->left = (*p)->right = NULL;
if (a[i] >= 'a' && a[i] <= 'z') return i; // If the character is an operand
i = add(&(*p)->left , a, ++i);
if (a[i] == '\0') return i; // If its the end of the expression
i = add(&(*p)->right, a, ++i);
return i;
}
i变量用于计算字符串的方式。您必须在main中修改您的初始添加调用以适应。