使用负节点构建表达式树

时间:2020-05-08 19:51:01

标签: c

我在构建像这样的二叉树时遇到了麻烦: 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

1 个答案:

答案 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中修改您的初始添加调用以适应。