二叉搜索树(BST)的删除算法原理解析

二叉搜索树的删除算法主要分两种情况:

1、要删除的节点只有一个孩子(左孩子或右孩子),这种情况比较简单,只需要将该孩子连接到当前节点的父节点即可。

下面重点讲讲第二种情况:

2、第二种情况便是要删除的节点有两个孩子,这个时候的算法就比较复杂(相比较于只有一个孩子的情况)。首先我们需要找到待删除节点的左子树上的最大值节点,或者右子树上的最小值节点,然后将该节点的参数值与待删除的节点参数值进行交换,最后删除该节点,这样需要删除的参数就从该二叉树中删除了。

对于第二种情况,由于需要进行节点交换,刚接触的时候,可能会困惑,进行交换之后的二叉树是否还满足二叉搜索树的结构特点呢?以与左子树最大节点交换为例,尽管左子树的根节点比其父节点小,但是左子树的节点中存在比左子树的根节点大的节点,这样如何保证其比右子树的根节点小呢?比如下面一个BST就不满足算法:

                                                             39

                                               30                         44

                                       27            36

                                22          31              45(大于44)

                                                          37

上面的二叉树乍一看满足BST的结构特点:左孩子的值小于父亲,右孩子的值大于父亲

但是如从BST构成的角度,一步一步的分析,就会发现节点45应该在右子树上。

其实,上述二叉树(如果是BST)的左子树的所有节点都应小于39,左子树节点的最大值也应该在30与39之间,不会存在大于44的情况。

由上讨论,便知不存在左子树最大节点大于右子树根节点的情况了。(同理也不会存在右子树最小值大于左子树根节点的情况)

下面附上一段BST删除算法代码(源于Clifford A.Shaffer 《date structures and algorithm analysis in C++》):

(此段代码的删除不是简单意义上的删除,而是对二叉树的重构)

//return the root of the updated tree after removal
//t point to the removed node
BinNode<Elem>* removehelp(BinNode<Elem>* subroot, const Elem& e, BinNode<Elem>*& t) {
	if (subroot == NULL) return NULL;
	else if (e < subroot->val())
		subroot->setLeft(removehelp(subroot->left(), e, t));
	else if (e > subroot->val())
		subroot->setRight(removehelp(subroot->right(), e, t));
	else { // Found it: remove it
		BinNode<Elem>* temp;
		t = subroot;
		if (subroot->left() == NULL)
			subroot = subroot->right();
		else if (subroot->right() == NULL)
			subroot = subroot->left();
		else {  // Both children are non-empty
			subroot->setRight(deletemin(subroot->right(), temp));
			Elem te = subroot->val();
			subroot->setVal(temp->val());
			temp->setVal(te);
			t = temp;
		}
	}
	return subroot;
}
//return the root of the tree after remove the node with the minimum value
BinNode<Elem>* deletemin(BinNode<Elem>* subroot, BinNode<Elem>*& min) {
	if (subroot->left() == NULL) {
		min = subroot;
		return subroot->right();
	}
	else { // Continue left
		subroot->setLeft(deletemin(subroot->left(), min));
		return subroot;
	}
}
 

猜你喜欢

转载自blog.csdn.net/huangyimo/article/details/81147302
今日推荐