二叉搜索树

什么是二叉搜索树

二叉搜索树对于任何节点x,其左子树中的关键字最大不超过x的关键字。其右子树中的关键字最小不低于x的关键字。如图所示:
在这里插入图片描述

查询二叉搜索树

一、在二叉搜索树中查找指定的值,可以利用二叉树的性质很容易就很写出代码:
1、如果值等于根节点的值,结束;
2、如果值大于根节点,递归的在右子树中查找;
3、如果值小于根节点,递归的在左子书中查找;

TRee_search(x,k){
	if x==NULL && k == x.key
		return x;
	if (k < x.key)
		return Tree_search(x.left,k);
	else
		return Tree_search(x.right,k);
}

由于递归效率较低,我们可以展开递归的过程

TRee_search(x,k){
	while(x != NULL && k != x.key){
		if(key < x.key)
			x = x.left;
		else
			x =x.right;
	}
	return x;

}

二、查询最大关键元素和最小的关键元素
由二叉搜索树的性质可以很容易的得出:
1、最小的元素一定在左子树中;
2、最大的元素一定在右子树中;

Tree_MAX(x){
	while(x.right !=NULL)
		x = x.right;
	return x;
}

Tree_MIN(x){
	while(x.left !=NULL)
		x = x.left;
	return x;
}

三、查找后继
查找一个元素的后继节点分为两总情况:
1、如果节点x的右子树非空,那么x的后继就是x的右子树中最小的值;
2、如果节点x的右子树为空,但是有一个后继节点y,那么y就是x的最底层的祖先,并且y的左孩子也是x的祖先,找到y只需要简单地重x开始沿树而上直到遇到节点:这个节点是父节点的左孩子。

Tree_Successor(x){
	if x.right != NULL
		return Tree_MIN(x.right)
	y = x.p // 父节点
	while(y!=NULL && x==y.right){
		x = y;
		y = y.p;
	}
	return y;
}

四、插入一个元素
插入的元素不能破坏搜索树的性质。

Tree_insert(T,z){
	y = new TreeNode();
	x = T.root;
	while(x !=NULL){
		y = x;
		if (z.key < x.key)
			x = x.left;
		else
			x = x.right;
	}
	z.p = y;
	if(y == NULL)
		T.root = z;
	else if(z.key < y.key)
		y.left = z;
	else
		y.right = z;
}

五、 删除元素
删除元素的问题比较困难,因为删除之后不能破坏搜索二叉树的结构,删除元素的情况可以分为以下三种:
1、如果要删除的节点z没有孩子节点,这种情况最简单,直接把节点删除就可以;
2、如果要删除的节点z只有一个孩子,那么把这个孩子提升到z在树中的位置就可以;
3、如果要删除的节点z有两个孩子,找到z的后继元素y(y一定没有左子树有兴趣的同学可以证明以下反正法很好证明)这种情况又分为两种情况:
3.1 如果后继元素y是z的孩子,那么用y替换z的位置,y的左子树=z的子树
3.2 如果后继元素y不是z的孩子,那么用y的右孩子x来代替y的位置,然后y代替z的位置。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

为了在二叉搜索树中移动子树,定义移动子树的过程Transolant,作用是用一棵子树代替另一颗子树的位置,假设用根节点为v的子树替换以u为根节点的子树,那么节点u的双亲变为v的双亲

Transolant(T,u,v){
	if(u.p==NULL)//u没有父节点
		T.root = v;
	else if(u == u.p.left)//u是父节点的左孩子
		u.p.left = v;
	else
		u.p.right = v;
	if (v != NULL)
		v.p = u.p//改变父节点的指向
}
Tree_Delete(T,z){
	if(z.left==NULL)//处理只有一个孩子的问题
		Transolant(T,z,z.right);
	else if(z.right==NULL)
		Transolant(T,z,z.left);
	else
		y = Tree_MIN(z.right)//找到z的后继节点:这里要记住如果一个节点有两个孩子节点,那么他的后继节点没有左孩子,前驱节点没有右孩子
		if(y.p !=z){//处理情况3.2
			Transolant(T,y,y.right);
			y.right = z.right;
			y.right.p = y;
		}
		Transolant(T,z,y);
		y.left = z.left;
		y.left.p = y;
		
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值