这个指针算法为什么不起作用?
问题描述:
在我的节目,我有被定义二叉树如下:这个指针算法为什么不起作用?
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
有一点要注意的是,我把这个功能另一个在它的末尾添加空字符的函数,它不应该影响输出,但我认为可能值得一提。
为什么使用数组索引的第二个版本工作但第一个版本没有?
答
它不起作用,因为您忽略了递归子呼叫返回的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
和当前字符指针。