(算法总结)二叉排序树的节点删除(leetcode 450)

二叉排序树的节点插入和查找已经在本人的上一篇博文中讲解过了,大家可以参考:

https://blog.csdn.net/little_fire/article/details/80798663

本篇博文将为大家重点讲解一下二叉排序树的节点删除操作,对应的是leetcode的第450题目,希望为大家带来帮助。

首先,根据二叉排序树的性质可知,二叉排序树的待删除节点,可能存在以下三种情况:

(1)既包含左子树、又包含右子树;

(2)只包含左子树或只包含右子树;

(3)叶子节点;

其中后两种可以合并处理。

删除节点时,需要修改目标节点的父节点指针,因此,需要定义一个变量去保存一个父节点指针,删除操作就是要修改父节点指针。因此,重新定义节点查询函数BST_search,如下:

TreeNode* BST_search(TreeNode* node, int value, TreeNode* &parent) {
	while (node) {
		if (node->val == value){
			break;
		}
		parent = node;
		if (value < node->val)
		{
			node = node->left;
		} else {
			node = node->right;
		}
	}
	return node;
}

对于(2)(3)两种情况,即目标节点只存在最多一个子树的情况,我们定一个删除节点的操作delete_node,需要传入待删除节点指针及其parent指针。

void delete_node(TreeNode* node, TreeNode* parent) {
	if (node->val < parent->val) {
		if (node->left) {
			parent->left = node->left;
		} else {
			parent->left = node->right;
		}
	} else {
		if (node->right) {
			parent->right = node->right;
		} else {
			parent->right = node->left;
		}
	}
}

接下来,我们需要考虑情况(1),即包括左子树和右子树,此时需要获取目标节点的中序遍历后继节点,因为此时目标节点存在左子树,也存在右子树,后继节点即目标节点右子树的最左节点。函数如下:

TreeNode* find_successor(TreeNode* node, TreeNode* &parent) {
	parent = node;
	TreeNode* ptr = node->right;
	while (ptr->left) {
		parent = ptr;
		ptr = ptr->left;
	}
	return ptr;
}

最后,我们就可以将整个程序整合一下,这里还需要考虑一下,当被删除节点是根节点(parent=NULL),且根节点只有至多一个子树的情况,此时,直接将root赋值给root存在的那个子树。若待删除节点不存在(未找到),直接返回root。整合后的代码如下:

TreeNode* BST_delete_node(TreeNode* root, int key) {
	TreeNode* parent;
	TreeNode* node = delete_node(root, key, parent);
	if (!node) {
		return root;
	}
	if (node->left && node->right) {
		TreeNode* successor = find_successor(node, parent);
		node->val = successor->val;
		delete_node(successor, parent);
		return root;
	}
	if (parent) {
		delete_node(node, parent);
		return root;
	}
	if (root->left) {
		return root->left
	} else {
		return root->right;
	}
}


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值