为什么这个指针算法不起作用?

时间:2017-08-10 01:04:39

标签: c pointers binary-tree

在我的程序中,我有一个二进制树,定义如下:

struct node {
    char value; 
    struct node *left, *right;
};

在我的程序中,我试图编写一个函数,以索引顺序返回每个节点值的字符串(从上到下,从右到左遍历)。

为了尝试这样做,我写了以下功能:

char *to_string_util(struct node *root, char *str) {

    if (!root) return str;

    *str++ = root->value;

    // If not NULL
    if (root->left) to_string_util(root->left, str);
    if (root->right) to_string_util(root->right, str);

    return str;
}

这似乎应该可行,但唉,它没有。我已经通过使用数组索引来使它工作,但这是有效的,因为它需要引入另一个变量。

这是适用的版本:

char *to_string_util(struct node *root, char *str, int *cur_pos) {

    if (!root) return str;

    str[(*cur_pos)++] = root->value;

    if (root->left) to_string_util(root->left, str, cur_pos);

    if (root->right) to_string_util(root->right, str, cur_pos);

    return str;
}

鉴于树:

             +
           /   \
          *     *
         / \   / \
         a  a  b  b 

结果应为:+*aa*bb

有一点需要注意的是,我在另一个函数中调用此函数,该函数在其末尾附加一个空字符,这不应该影响输出,但我认为可能值得一提。

为什么第二个版本使用数组索引工作但第一个版本不工作?

1 个答案:

答案 0 :(得分:4)

它不起作用,因为您忽略了递归子调用返回的str的新值。您的函数旨在更新str的值,并通过return str;返回新值。而你只是丢弃了返回的值。因此,在每个递归级别,对右子树的调用将覆盖由递归调用写入左子树的数据。

这可能更接近您的想法

// If not NULL
if (root->left) str = to_string_util(root->left, str);
if (root->right) str = to_string_util(root->right, str);

当然,你应该记得最后将你的字符串归零。

如果您的功能以

开头
if (!root) return str;

然后递归的子调用真的不需要空检查,可以简化为

str = to_string_util(root->left, str);
str = to_string_util(root->right, str);

(除非您将其视为优化)。

您的基于索引的版本不再依赖于str的更新(并且根本不更新)。这取决于位置值*cur_pos的更新。由于位置值在不同级别的递归之间通过引用传递,因此所有级别的递归都会看到这些更新。

您也可以在第一个版本中使用相同的技术,即通过引用传递指针值 。但是为此你必须将str作为char **str(指向指针)并使用*str和当前字符指针。