二叉查找树——查找、插入、删除 思路+代码(Java)

二叉查找树(也叫二叉搜索树、二叉排序树)
因为它要求左子树小于根结点,右子树大于根结点(对于每个结点均如此),这就说明了二叉树具有有序的特定。

二叉树查找的效率取决于数的高度。


定义结点类:

public class TreeNode {
	    int val = 0;
	    TreeNode left = null;
	    TreeNode right = null;

	    public TreeNode(int val) {
	        this.val = val;

	    }
	}


1.查找(查找元素K)

思路:

  1. 查找从根结点开始,如果树为空,返回NULL
  2. 若搜索树非空,则根结点关键字和X进行比较, 并进行不同处理:
  • X小于根结点键值,只需在左子树中继续搜
  • 如果X大于根结点的键值, 在右子树中进行继续搜索;
  • 若两者比较结果是相等,搜索完成,返回结点。 

//递归方式(尾递归)
	public TreeNode Find(int K,TreeNode root){
		if(root==null)
			return null;
		if(K>root.val)
			return Find(K,root.right);//在右子树中继续查找
		else if(K<root.val)
			return Find(K,root.left);//在左子树中继续查找
		else 
			return root;
	}
//由于非递归函数的执行效率高,可将“尾递归”改为迭代函数
//	public TreeNode Find(int K,TreeNode root){
//		while(root!=null){      
//			if(K>root.val)
//				root=root.right;
//			else if(K<root.val)
//				root=root.left;
//			else
//				return root;
//		}
//		return null;
//	}

2.查找最大和最小元素

思路:最大元素一定是在树的最右分枝的端结点
            最小元素一定是在树的最左分枝的端结点 
以下查找用了两种不同的方式
public TreeNode FindMax(TreeNode root){
		if(root!=null)
			while(root.right!=null)  //沿右分支继续查找,直到最右叶结点
				root=root.right;
		return root;
	}
	
public TreeNode FindMin(TreeNode root){
		if(root==null)
			return null;  //空的二叉搜索树,返回null
		else if(root.left==null)
			return root;  //找到最左叶结点并返回
		else
			return FindMin(root.left); //沿左分支继续查找
	}

3.插入

思路:关键是要找到元素应该插入的位置,可以采用与Find类似的方法 
public TreeNode Insert(int K,TreeNode root){
		if(root==null){ //若原树为空, 生成并返回一个结点的二叉搜索树
			TreeNode node=new TreeNode(K);
			node.left=null;
			node.right=null;
			root=node;	
		}
		else if(K<root.val){ 
			root.left=Insert(K,root.left);//递归插入左子树
		}
		else if(K>root.val){
			root.right=Insert(K,root.right);//递归插入右子树
		}
		return root;
	}

4.删除

考虑三种情况:
  1. 要删除的是叶结点:直接删除, 并再修改其父结点指向为null
  2. 要删除的结点 只有一个孩子 结点 : 将其 父结点 指向 要删除结点的 孩子结点 
  3. 要删除的结点 有左、右两棵子树:
    用另一结点替代被删除结点: 右子树的最小元素 或者 左子树的最大元素 (因为左子树的最大元素一定在右边没有右儿子。
    右子树的最小元素一定在最左边,没有左子)
 
public TreeNode Delete(int K,TreeNode root){
		TreeNode node;
		if(root==null)
			System.out.println("要删除的元素不存在");
		else if(K<root.val){
			root.left=Delete(K,root.left); //左子树递归删除
		}
		else if(K>root.val){
			root.right=Delete(K,root.right); //右子树递归删除
		}
		else 
			if((root.left!=null) && (root.right!=null)){ //被删除结点有左右两个子结点 
			node=FindMin(root.right); //在右子树中找最小的元素填充删除结点
			root.val=node.val;
			root.right=Delete(root.val,root.right); //在删除结点的右子树中删除最小元素
			}
			else{  //被删除结点有一个或无子结点
				if(root.left==null) //有右孩子或无子节点
					root=root.right;
				else if(root.right==null) //有左孩子或无子节点
					root=root.left;
			}
		return root;
	}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值