二叉查找树

本文详细介绍了二叉查找树的基本概念、性质及实现方法,包括查找、插入与删除操作的具体步骤与时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉查找树

二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树

定义

二叉排序树或者是一棵空树,或者是具有下列性质的二叉树
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。

树的节点

二叉查找树要求所有的项都能排序,要写出一个一般的类,我们使用Comparable接口。

代码:

public class BinaryNode<T> {
T element;
BinaryNode<T> left;
BinaryNode<T> right;
BinaryNode(T element){
	this(element,null,null);
}
BinaryNode(T element,BinaryNode<T> lt,BinaryNode<T> rt){
	this.element=element;
	this.left=lt;
	this.right=rt;
}
}

BST树

代码:

public class BST<T extends Comparable<? super T>> { 
private BinaryNode<T> root;
public boolean isEmpty(){
	return root==null;
}
public boolean find(T x){//查询指定值的节点
	return find(x,root);
}
public T findMin(){//查找最小节点的值
	if(isEmpty())
		throw new RuntimeException();
	return findMin(root).element;
}
//同理查找最大
public void insert(T t){//插入
	root=insert(t,root);
}
public void remove(T t){//删除
	root=remove(t,root);
}
public boolean find(T x,BinaryNode<T> root){
	//见查找
}
public BinaryNode<T> findMin(BinaryNode<T> root){
	//见查找
}

public BinaryNode<T> insert(T t,BinaryNode<T> root){
	//见插入
}
public BinaryNode<T> remove(T t,BinaryNode<T> root){
	//见删除
}

}


查找

步骤:

若根结点的关键字值等于查找的关键字,成功

否则,若小于根结点的关键字值,递归查左子树。
若大于根结点的关键字值,递归查右子树。
若子树为空,查找不成功。

最坏时间O(n)
平均O(logn)
平均:参考百度百科



在一般情况下,设 P(n,i)为它的左子树的结点个数为 i 时的平均查找长度。如图的结点个数为 n = 6 且 i = 3; 则 P(n,i)= P(6, 3) = [ 1+ ( P(3) + 1) * 3 + ( P(2) + 1) * 2 ] / 6= [ 1+ ( 5/3 + 1) * 3 + ( 3/2 + 1) * 2 ] / 6
注意:这里 P(3)、P(2) 是具有 3 个结点、2 个结点的二叉分类树的平均查找长度。 在一般情况,P(i)为具有 i 个结点二叉分类树的平均查找长度。
P(3) = (1+2+2)/ 3 = 5/3
P(2) = (1+2)/ 2 = 3/2∴ P(n,i)= [ 1+ ( P(i) + 1) * i + ( P(n-i-1) + 1) * (n-i-1) ] / n
∴ P(n)=
P(n,i)/ n <= 2(1+I/n)lnn
因为 2(1+I/n)lnn≈1.38logn 故P(n)=O(logn)

代码:

查找最小:

public BinaryNode<T> findMin(BinaryNode<T> root){
	if(root.left==null)
		return root;
	return findMin(root.left);
}
查找:


public boolean find(T x,BinaryNode<T> root){
	if(root==null)
		return false;
	int result=x.compareTo(root.element);
	if(result<0)
		return find(x,root.left);
	else if(result >0)
		return find(x,root.right);
	else
		return true;
}

插入

步骤:

首先执行查找算法,找出被插结点的父亲结点。
若查到已知节点,则什么都不用做(或做一些更新)
判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。
二叉树为空。则首先单独生成根结点。

最坏时间:有序O(N),一连串插入操作O(N^2)

平均:O(logN)

代码:


public BinaryNode<T> insert(T t,BinaryNode<T> root){
	if(root==null)
		return new BinaryNode<T>(t,null,null);
	int result=t.compareTo(root.element);
	if(result<0)
		root.left=insert(t,root.left);
	else if(result>0)
		root.right=insert(t,root.right);
	else
		;//do nothing
	return root;
}

删除

步骤

分三种情况:

1.若节点p为叶子节点,即左子树(PL)和右子树(PR)都为空时,直接删除。

2.若节点p只有左子树PL或者右子树(PL)时,只要让PL或PR直接成为父节点的左子树或右子树即可。

3.若节点p有左右两个子树,则用右子树最小的那个节点代替p节点,并递归的删除那个节点,

最坏时间:O(N)

平均时间:O(logn)

代码

public BinaryNode<T> remove(T t,BinaryNode<T> root){
	if(root==null)
		return null;
	int result=t.compareTo(root.element);
	if(result<0)
            root.left=remove(t,root.left);
	else if(result>0)
		root.right=remove(t,root.right);
	else if(root.left!=null&&root.right!=null){//两个子节点
		root.element=findMin(root.right).element;//用右子树最小的节点替代当前节点
		root.right=remove(root.element,root.right);//删除右子树最小节点
		}
	else{//只有一个节点或没有节点
		return root.left==null?root.right:root.left;
	}
	return root;
	}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值