性质:
- 每个结点都有一个作为搜索依据的关键码(key),所有结点的关键码互不相同。
- 左子树上的所有结点的关键码都小于根结点的关键码。
- 右子树上的所有结点的关键码都大于根结点的关键码。
- 左子树和右子树也是二叉搜索树。
二叉搜索树的搜索
从根结点开始,沿着某一个分支逐层向下进行比较判断的过程。可以是一个递归的过程。假设想要在二叉搜索树搜索关键码为x,搜索过程从根结点开始,如果指针为NULL,则搜索失败;否则用给定值x与根结点比较,等于根结点的关键码,搜索成功,返回信息;若小于根结点的关键码,则递归搜索根结点的左子树;否则,递归搜索根结点的右子树。
template<class E, class K>
BSTNode<E,K> *BST<E,K>::Search(const K x, BSTNode<E,K> *ptr){
if(ptr==NULL) return NULL;
else if(x<ptr->data) return Search(x,ptr->left);
else if(x>ptr->data) return Search(x,ptr->right);
else return ptr;
}
二叉搜索树的插入
指针类型作形参(实际是按值传递,只是指针的地址不变)————该形参变量在函数中改变了对原来的实参变量没有任何影响
引用型指针类型作形参————该形参变量在函数中改变了,原实参变量也会跟着改变
template<class E, class K>
bool BST<E,K>::Insert(const E& el, BSTNode<E,K> *&ptr){//参数表中的引用型指针参数
if(ptr==NULL){//递归到空树位置,将创建的新结点地址送给ptr,因此用引用
ptr=new BSTNode<E,K>(el);//新结点作为叶结点插入,因为是递归。
if(ptr==NULL){cerr<<"Out of space"<<endl; exit(1);}
return true;
}
else if(el<ptr->data) Insert(el,ptr->left);
else if(el>ptr->data) Insert(el,ptr->right);
else return false;
}
二叉搜索树的删除
- 如果删除叶结点,只需将其父结点指向它的指针清零,再释放它即可。
- 如果被删结点右子树为空,可以拿它的左子女结点顶替它的位置,再释放它。如果被删结点左子树为空,可以拿它的右子女结点顶替它的位置,再释放它。
- 如果被删结点左右子树都不为空,可以在它的右子树寻找中序下的第一个结点(关键码最小),用它填补到被删结点中,再处理找到的这个结点的删除问题。
template<class E, class K>
bool BST<E,K>::Remove(const K x, BSTNode<E,K> *&ptr){
BSTNode<E,K> *temp;
if(ptr!=NULL){
if(x<ptr->data) Remove(x,ptr->left);
else if(x>ptr->data) Remove(x,ptr->right);
else if(ptr->left!=NULL && ptr->right!=NULL){
temp=ptr->right;
while(temp->left!=NULL) temp = temp->left;//到右子树寻找中序下第一个结点
ptr->data=temp->data;//用该结点的数据代替根结点数据
Remove(ptr->data,ptr->right);//删除根结点的右子树中该点的数据
}else {//ptr指示关键码为x的结点,只有一个或零个子女
temp = ptr;
if(ptr->left==NULL) ptr=ptr->right;
else ptr = ptr->left;
delete temp;
return true;
}
}
return false;
}