全部数据结构、算法及应用课内模板请点击:https://blog.csdn.net/weixin_44077863/article/details/101691360
二叉搜索树(二叉排序树)(binary search tree)(BST)
二叉搜索树很简单,就是左子树的所有结点的键值小于根结点,右子树的所有结点的键值大于根结点
这样就能使插入与搜索达到log级别
非常简单
稍微说一说删除吧
删除分两类:合并删除和复制删除
1、合并删除:把当前结点删掉,左子树右子树对接到一起,于是有两种对接想法
①左子树挪到被删结点处,右子树接到左子树中最大(最右)结点的右侧(教材代码,常用)
②右子树挪到被删结点处,左子树接到右子树中最小(最左)结点的左侧
2、复制删除:
①将左子树中最大(最右)结点的值赋给被删除结点,并把这个最大结点删除,这个最大结点删除起来就会方便许多,因为该结点必然没有右儿子,于是只需要将左儿子挪到这个结点处即可,但写的时候要注意细节,上述情况是最大结点的父结点的右 指向他的左儿子,如果这个结点的父结点恰好是被删除结点,那么接儿子的时候注意是左接他的左儿子(教材代码,常用)
②将右子树中最小(最左)结点的值赋给被删除结点,并把这个最小结点删除,具体细节可仿上,略
PS:不管是合并删除还是复制删除,待删除结点只有一个子树的话,就直接挪过去就好,左右子树都有再用上述手段
再就是删除的时候要记得删根特判。
二叉搜索树模板如下:(删除取常用方法)
template <class T>
class Node{
public:
T x;
Node<T> *l,*r;
Node():l(0),r(0){}
Node(const T& x):x(x),l(0),r(0){}
Node(const T& x, Node<T> *l, Node<T> *r):x(x),l(l),r(r){}
};
template <class T>
class BinarySearchTree{
private:
Node<T> *root;
public:
BinarySearchTree():root(0){}
void insert(const T& x){
Node<T> *p=root,*pre=NULL;
while(p){
pre=p;
if(x>p->x) p=p->r;
else p=p->l;
}
if(!root) root=new Node<T>(x);
else if (x>pre->x) pre->r=new Node<T>(x);
else pre->l=new Node<T>(x);
}
Node<T>* search(T x){
Node<T> *cur=root;
while(cur&&cur->x!=x){
if(x>cur->x) cur=cur->r;
else cur=cur->l;
}
return cur;
}
void delete_copy(T x){//复制删除
Node<T> *p=root,*fa,*pre,*tmp;
while(p&&p->x!=x){
if(x>p->x) fa=p,p=p->r;
else fa=p,p=p->l;
}
if(!p) return;
tmp=p;
if(!(p->r)){//无右子树,左子树复制到被删除结点处
if(root==p) root=p->l;
else if(fa->l==p) fa->l=p->l;
else fa->r=p->l;
}
else if(!(p->l)){//无左子树,右子树复制到被删除结点处
if(root==p) root=p->r;
else if(fa->l==p) fa->l=p->r;
else fa->r=p->r;
}
else{
tmp=p->l;
pre=p;
while(tmp->r){//左子树中最大的
pre=tmp;
tmp=tmp->r;
}
p->x=tmp->x;
if(pre==p) p->l=tmp->l;
else pre->r=tmp->l;
}
delete tmp;
}
void delete_merge(T x){//合并删除
Node<T> *p=root,*fa,*tmp;
while(p&&p->x!=x){
if(x>p->x) fa=p,p=p->r;
else fa=p,p=p->l;
}
if(!p) return;
if(!(p->r)){//无右子树,左子树复制到被删除结点处
if(root==p) root=p->l;
else if(fa->l==p) fa->l=p->l;
else fa->r=p->l;
}
else if(!(p->l)){//无左子树,右子树复制到被删除结点处
if(root==p) root=p->r;
else if(fa->l==p) fa->l=p->r;
else fa->r=p->r;
}
else{
tmp=p->l;
while(tmp->r) tmp=tmp->r;//左子树中最右的
tmp->r=p->r;
tmp=p;
if(p==root) root=p->l;
else if(fa->l==p) fa->l=p->l;//左子树的根结点代替被删除结点
else fa->r=p->l;
}
delete tmp;
}
};