二叉排序树

二叉排序树是具有以下性质的二叉树:

1)如果左子树不为空,那么左子树的值均小于根节点的值,如果右子树不为空,那么右子树的值均大于根节点的值;

2)左右子树也分别是二叉排序树;

又称为二叉搜索树,二叉查找树。

二叉树的基本运算包括查找,插入和删除,其中以删除最难,这里就不介绍查找。

二叉树的插入:

需要认识到,二叉排序树插入的节点一定是作为叶子节点添加进去的;

//二叉排序树的插入
public static Node InsertNode(Node t,KeyType k)
{
	Node f,p,s;//声明几个节点,s是新插入的点,p是s的双亲,f是p的双亲
	p = t;
	while(p)
	{
		if(p.data == k)
		{
			return t;
			System.out.println("存在k,不需要插入");
		}
		else
		{
			f = p;
			if(p.data<k) p = p.rchild;
			else p =p.lchild;			
		}
	}//找到要插入的点的双亲p
		s = new Node(k);
		s.lchild=null;
		s.rchild=null;//新建节点
		if(t==null) t=s;
		else if(p.data<k) p.rchild = s;
		else p.lchild = s;//根据大小插入s
		return t;
}


在二叉排序树中删除一个节点:

在二叉排序树中删除一个节点,首先要查找,如果没有这个点,查找失败,否则,根据下面的方法进行删除。
设待删除节点指针p,双亲节点为f,分三种情况:
1)p为叶子节点,那么删除此节点不会影响排序树的特性,直接删除,只需要把该节点的双亲节点相应位置置为null
2)p节点是单支节点,即p节点只有左子树Pl或者右子树Pr,此时只需要用Pl或Pr替代p的位置即可
3)p节点是双支节点,既有左子树,又有右子树,此时要按中序遍历保持排序树特性来进行删除,有两种方法:
1,用p的右子树pr代替以p为根的子树,即以pr为根的子树上升,再根据中序遍历序列(中序遍历保持不变),调整p的原左子树pl,
让他作为以pr为根的子树中序遍历时第一个节点的左子树(保证中序遍历是pl依然是在pr前面);
2,用p的直接直接后继(或直接前驱)代替p节点,这个节点只能是叶子或者单支节点(肯定存在),再按1)或2)删除p;
从上述的调整方案可以看到,按3)中的1方法,排序树的长度是可能会增加的,而按照2)方法排序数的高度肯定不会增加,
还有可能减小。
下面按2)方法实现一个节点的删除;

public static Node DeleteNode(Node <DataType> t,KeyType k)
//在根节点为t的二叉排序树中删除元素为k的节点,并返回根节点
{
//声明几个节点,p是待删除节点,f是p的双亲节点,s是p的中序遍历中的直接后继节点,pre是s的双亲节点
	Node <DataType> f,s,p,r,pre;
	//先搜索待删节点
	p = t;
	while(p && p.data!=k)
	{
		f = p;
		if(p.data<k)
			p = p.lchild;
		else
			p = p.rchile;
	}
	if(p==null)
	{
			System.out.println("不存在此节点,删除失败!");
			return t;
	}
	if(p.lchild && p.rchild)
	{
			pre = p;
			s = p.rchild;
			while(s.lchild!=null)
			{
				pre = s;
				s = s.lchild;
			}//查找到p点中序遍历的直接后继节点s
			p.data = s.data;  // s点取代待删p点
			r = s.rchild; // s的右子树上升(如果存在)
			if(pre == p)  pre.rchild = r;
			else  pre.lchild = r;
	}
	else  //情况1)和2)
 {
		if(p.lchild == null) r = p.lchild;
		else if(p.rchild == null) r = p.rchild;
		if(f == null)
		{
					return t;//待删的是根节点
		}
		else if(f.lchild==p) f.lchild = r;
		else if(f.rchild==p) f.rchild ==r;
	}
	return t;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值