二叉树的指针操作误区:
力扣的一道简单题:https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/
问题描述:
镜像二叉树,很快就想到用递归去做,然后写下了如下的代码:
TreeNode* mirrorTree(TreeNode* root) {
if (!root)
return root;
reverseRoot(root, root->left, root->right);
return root;
}
void reverseRoot(TreeNode* root, TreeNode* left, TreeNode* right)
{
if (!root)
return;
TreeNode* temp = left;
left = right;
right = temp;
if (left)
reverseRoot(left, left->left, left->right);
if (right)
reverseRoot(right, right->left, right->right);
}
结果实际一跑,程序完全没有修改树的结构,root原封不动的返回了。
原因分析:
敏感的大佬看到原封不动返回应该就能发现是因为我直接修改了函数中的形参left和right导致的。
left = right;
right = temp;
left作为形参,在初始化的时候指向了root->left。然而当执行left = right的时候,只是修改了left的指向,从指向root->left变成了root->right。这意味着root->left/right即树本身的结构并没有发生任何更改。
解决方案:
将代码修正成如下所示即可,切记不得修改left和right这两个“无用”的形参,要从源头下手修改root->left/right。这里插多一嘴,因为left形参指向的是root->left,当我实际修改了“root->left = right”后,left的指向也跟随变成了“root->right”。
void reverseRoot(TreeNode* root, TreeNode* left, TreeNode* right)
{
if (!root)
return;
TreeNode* temp = left;
root->left = right;
root->right = temp;
if (left) //这个时候left指针其实指的是root->right
reverseRoot(left, left->left, left->right);
if (right) //这个时候right指针其实指的是root->left
reverseRoot(right, right->left, right->right);
}
其实这个时候发现reverseRoot的left、right参数完全是多余的,完全可以用root->left/right取代。而且还不会因为自己的粗心直接对这个形参进行修改而产生bug。
TreeNode* mirrorTree(TreeNode* root) {
if (!root)
return root;
reverseRoot(root);
return root;
}
void reverseRoot(TreeNode* root)
{
if (!root)
return;
TreeNode* temp = root->left;
root->left = root->right;
root->right = temp;
if (root->left) //这个时候root->left指针其实指的是root->right
reverseRoot(root->left);
if (root->right) //这个时候root->right指针其实指的是root->left
reverseRoot(root->right);
}
综上所述,对二叉树进行操作,一定要直接修改root->left/right而不是形参!