二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树。
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值。
- 非空右子树的所有键值大于其根结点的键值。
- 左、右子树都是二叉搜索树。
1、BST 的查找操作
(1)查找从根结点开始,如果树为空,返回NULL
(2)若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:
① 若X小于根结点键值,只需在左子树中继续搜索;
② 如果X大于根结点的键值,在右子树中进行继续搜索;
③若两者比较结果是相等,搜索完成,返回指向此结点的指针。
BinTree* Find(BinTree* BST, int x){
if(!BST) return nullptr;
if(x < BST->val){
BST = Find(BST->left, x);
}
else if( x > BST->val){
BST = Find(BST->right, x);
}
else{
return BST;
}
}
BinTree* Find_nore(BinTree* BST, int x){
while (BST)
{
if(x < BST->val){
BST = BST->left;
}else if(x > BST->val){
BST = BST->right;
}else{
return BST;
}
}
return nullptr;
}
2. 查找最大和最小元素
首先说明的是:
①最大元素一定是在树的最右分枝的端结点上。
②最小元素一定是在树的最左分枝的端结点上。
BinTree* FindMax(BinTree* BST){
if(BST != nullptr){
while(BST->right != nullptr){
BST = BST->right;
}
}
return BST;
}
BinTree* FindMin(BinTree* BST){
if(BST != nullptr){
while(BST->left != nullptr){
BST = BST->left;
}
}
return BST;
}
3. 二叉搜索树的插入
BinTree* Insert(BinTree* BST, int x){
if(!BST){
BST = new BinTree(x);
}
else{
if(x < BST->val){
BST->left = Insert(BST->left, x);
}
else if(x > BST->val){
BST->right = Insert(BST->right, x);
}
}
return BST;
}
4. 二叉搜索树的删除
对于二叉搜索树的删除,相对来说就比较麻烦了。因为要考虑以下三种情况:
①要删除的是叶结点;
②要删除的结点只有一个孩子结点;
③要删除的结点有左、右两棵子树;
对于上述的三种情况,我们要怎么做呢?
情况①:
叶结点就是左右子树都为空的结点,既然左右子树都为空,删掉它并没什么后顾之忧,所以当我们要删除的是叶结点的时候,直接删除就好了。当然不要忘记一个重要的操作——删除之后要修改其父结点指针,即置为NULL。
情况②:
当要删除的结点只有一个孩子结点,我们删除该结点后需要考虑怎么处置它的孩子结点。因为被删除的结点的孩子无论是左孩子还是右孩子,都只会比被删除的结点的父结点小,所以我们只需要将被删除的结点的父结点的指针指向被删除的结点的孩子结点。
情况③:
当删除的结点有左、右两棵子树,我们删除该结点后需要考虑怎么处置它的孩子结点。此时最简单的办法就是用另一结点替代被删除结点,那我们要用哪一个结点呢?根据二叉搜索树的定义:每一个结点的右孩子都比自己大,左孩子都比自己小。要取哪一个结点替代被删除的结点同时又保证该特性呢?所以根据此情况,我们很快就能判断出用被删除结点的右子树的最小元素或者左子树的最大元素替代被删除结点。
BinTree* Delete(BinTree* BST, int x){
BinTree* tmp;
if(!BST) cout<< "没有找到要删除的元素" << endl;
else{
if(x < BST->val){
BST->left = Delete(BST->left, x);
}
else if( x > BST->val){
BST->right = Delete(BST->right, x);
}
else{
if(BST->left != nullptr && BST->right != nullptr){
tmp = FindMax(BST->left);
BST->val = tmp->val;
BST->left = Delete(BST->left, BST->val);
}
else{
tmp = BST;
if(BST->left == nullptr){
BST = BST->right;
}
else{
BST = BST->left;
}
delete(tmp);
}
}
}
return BST;
}