二叉搜索树的删除算法主要分两种情况:
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;
}
}