struct TreeNode
{
char data;
struct TreeNode *left, *right;
};
//依照前序遍历创建一颗二叉树
void A(struct TreeNode **root)
{
char c;
scanf("%c", &c);
if (c==' '){
*root = NULL;
}
else
{
*root = malloc(sizeof(struct TreeNode));
(*root)->data = c;
A(&(*root)->left);
A(&(*root)->right);
}
struct TreeNode *B(struct TreeNode *root)
{
char c;
scanf("%c", &c);
if (c==' ')
root = NULL;
}
else
{
root = malloc(sizeof(struct TreeNode));
root->data = c;
root->left = B(root->left);
root->right = B(root->right);
}
return root;
}
//函数C是错误的吗?
void C(struct TreeNode *root)
{
char c;
scanf("%c", &c);
if (c==' ')
{
root = NULL;
}
else
{
root = malloc(sizeof(struct TreeNode));
root->data = c;
C(root->left);
C(root->right);
}
}
1.上面是创建二叉树的三个函数,函数A和函数B的区别在哪?
2.为什么函数A非要用到二级指针而函数B却只需要一级指针?
3.函数C是错误的吗?为什么函数B可以用一级指针是对的呢?
1 区别就是A不用返回值,也能修改函数外的root指针,而B是在函数设置指针指向并返回函数内的指针
2 因为A要直接修改函数外的root指针,而B不是修改函数外的指针,而是返回一个新指针。这个问题回答过很多次了。
形参只是实参的拷贝,形参本身的内存地址和实参的内存地址不同(在不同的函数栈里),所以在函数内修改形参的内存,不能影响函数外的实参。
什么叫修改形参的内存?直接对形参(变量)赋值就是修改形参(变量)的内存,比如 int a=5;//a的内存信息为5, a=10;//赋值语句修改了a的内存信息为10
所以B的 root = malloc(sizeof(struct TreeNode)); 就是修改形参的内存,这个root和函数外的实参的内存空间不同,所以修改它并不会对实参的内存造成影响,所以必须把它做为返回值返回去,否则函数外就没法获得这个变化的值。(也就是通过返回值来把变化返回去,让函数外也能获得这个变化)
A为什么可以影响函数外的实参?因为A传进来的是实参的地址,而不是实参的值,且函数内没有修改形参的内存(也就是没用直接对形参用赋值语句),而是对形参解引用(也就是找到实参的地址)去赋值。什么叫解引用赋值?*xx=yy就是解引用赋值,即A是用*root = malloc(sizeof(struct TreeNode));来赋值的,*root就是函数外的实参(因为root是实参的地址,*root就是实参),所以A能改变函数外的指针指向新的地址。
要记住,要想在函数内修改函数外的变量,必须满足三个条件
一,形参必须用指针
二,必须是把实参的地址传给形参
三,函数内必须是对形参解引用赋值而不能直接对形参赋值