二叉树前驱节点和后继节点:一个二叉树中序遍历中某个节点的前一个节点叫该节点的前驱节点,某个节点的后一个节点叫后继节点
该题目中还有一个节点指向节点的父节点 parent,规定头节点的父亲节点的指针为空。
struct TreeNode{
int val;
struct TreeNode* left;
struct TreeNode* right;
struct TreeNode* parent;
};
思路:
1)寻找前驱:若该节点存在左子树,则其前驱节点为左子树最右边的节点;若该节点不存在左子树,则利用parent指针向父节点找,若满足该节点是其父节点的右节点,则该父节点为当前节点的前驱节点,若不满足则更新父节点为祖父节点,当前节点更新为其父节点,直到满足条件或者父节点为空,为空表示到达根节点依旧没有找到。
2)寻找后继:若该节点存在右子树,则其后继节点为右子树最左边的节点;若该节点不存在右子树,则利用parent指针向父节点找,若满足该节点是其父节点的左节点,则该父节点为当前节点的后继节点,若不满足则更新父节点为祖父节点,当前节点更新为其父节点,直到满足条件或者父亲节点为空,为空表示到达根节点依旧没有找到。
1)寻找前驱节点:先理解前半句 “若该节点存在左子树,则其前驱节点为左子树最右边的节点”。下面这颗二叉树的中序遍历为 :
4-2-5-1-6-3-7
找到一个存在左子树的节点如1节点,那么1节点的前驱节点为其左子树最右边的节点5,这是可行的。
下面理解后半部分 “若该节点不存在左子树,则利用parent指针向父节点找,若满足该节点是其父节点的右节点,则该父节点为当前节点的前驱节点,若不满足则更新父节点为祖父节点,当前节点更新为其父节点,直到满足条件或者父节点为空,为空表示到达根节点依旧没有找到” 我们找到一个不存在左子树的节点如6节点,如下图所示,则当前节点为6节点,其父节点parent为3节点,6节点不是3节点的右节点,所以更新父节点为祖父节点,当前节点更新为其父节点,那么当前节点为3节点,其父节点为1节点,满足当前节点是其父节点的右节点,所以parent指向的节点为6的前驱
代码实现:
TreeNode* getPreNode(TreeNode* root) {
if (root == NULL)
return root;
if (root->left != NULL) {//如果其左子树存在,则返回其左子树的最右边节点
return leftTreeMostRight(root->left);
}
else {//若果其左子树不存在,则向父节点寻找,满足当前节点是父节点的右孩子节点即可,否则向上更新当前节点和其父节点
TreeNode* father = root->parent;
while (father->right != root && father != NULL) {
root = father;
father = root->parent;
}
return father;//如果找到了就是满足father->right == root,如果没找到,则fathe指向NULL
}
}
TreeNode* leftTreeMostRight(TreeNode* p) {
/*
if(p->right==NULL)
return p;
while(p->right!=NULL)
p = p->right;
return p->parent;
*/
while (p != NULL)
p = p->right;
return p->parent;
}
2)寻找后继节点:先理解前半句“若该节点存在右子树,则其后继节点为右子树最左边的节点”,
下面这颗二叉树的中序遍历为 :
4-2-5-1-6-3-7
找到一个存在右子树的节点如1节点,那么1节点的后继节点为其右子树最左边的节点6,这是可行的。
下面理解后半部分 “若该节点不存在右子树,则利用parent指针向父节点找,若满足该节点是其父节点的左节点,则该父节点为当前节点的后继节点,若不满足则更新父节点为祖父节点,当前节点更新为其父节点,直到满足条件或者父亲节点为空,为空表示到达根节点依旧没有找到” 我们找到一个不存在右子树的节点如6节点,如下图所示,则当前节点为6节点,其父节点parent为3节点,6节点是3节点的左节点,满足条件,所以3节点是6节点的后继节点。
下面再考虑节点5,不存在右子树,那么更新如下图所示,当前节点5不是父节点2的左节点,则向上更新当前节点和父节点;当前节点更新为节点2,其父节点更新为节点1,节点2是节点1的左节点,满足当前节点是其父节点的左节点,所以父节点1为节点5的后继节点。
代码实现:
TreeNode* getPostNode(TreeNode* root) {
if (root == NULL)
return root;
if (root->right != NULL) {//如果其右子树存在,则返回其右子树的最左边节点
return getRightTreeMostLeft(root->right);
}
else {//若果其右子树不存在,则向父节点寻找,满足当前节点是父节点的左节点即可,否则向上更新当前节点和其父节点
TreeNode* father = root->parent;
while (father != NULL && root != father->left) {
root = root->parent;
father = root->parent;
}
return father;
}
}
TreeNode* getRightTreeMostLeft(TreeNode* p) {
while (p != NULL)
p = p->left;
return p->parent;
}