二叉搜索树(二叉排序树)

全部数据结构、算法及应用课内模板请点击: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;
	}
};
发布了49 篇原创文章 · 获赞 0 · 访问量 1710

猜你喜欢

转载自blog.csdn.net/weixin_44077863/article/details/103114680