学习笔记—寻找二叉树的前驱节点和后继节点

二叉树前驱节点和后继节点:一个二叉树中序遍历中某个节点的前一个节点叫该节点的前驱节点,某个节点的后一个节点叫后继节点

该题目中还有一个节点指向节点的父节点 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;
}

 

 

  • 11
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无情的搬砖机器

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值