BST算法分析

本文深入讲解了BST树的增删查及查找最小值操作,通过Java代码实现,探讨了BST树的特性及其在查找和删除节点时的不同情况处理。

关于BST树的一些基本概念上一篇博客已经说过了,今天对bst树做了增,查、删以及查找最小值的操作,使用java代码实现。从代码中对这个bst有了更深的理解。
bst概念重申一下

来自百度百科:二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
直接上代码

1.创建一个树类

public class TreeNode {
	
	int val;
	TreeNode leftNode;
	TreeNode rightNode;
	public TreeNode(int x) {
		val = x;
	}
}

测试开始,代码中均使用的是递归,不用递归的话用while循环也可

public class BSTDemo {

	//数组生成 bst树
	public TreeNode BSTInsert(int[] arr) {
		TreeNode treeNode = null;
		for(int i=0;i<arr.length;i++){
			treeNode = insert(treeNode, arr[i]);
		}
		return treeNode;
	}
	
	//插入
	public TreeNode insert(TreeNode node,int a){
		if(node != null){
			if(node.val < a){
			 	node.rightNode = insert(node.rightNode, a);
			}else if(node.val > a){
				node.leftNode = insert(node.leftNode, a);
			}else if(node.val == a){
				node.val = a;
			}
		}else {
			return new TreeNode(a);
		} 
		return node;
	}
	
	/**
	 * 查找 这里是我刚开始搞错了,因为我以为二叉树搜索树会出现相同的值,自己试验以及百度之后,
	 * 发现不会存在相同的值。所以这下面有用到了BFS盲目搜索算法(详情看我另外一篇博客),
	 * 遍历整个二叉树,把符合条件的节点添加到list中。看网上说这又叫层次遍历。
	 * 
	 * 当知道BST不会出现重复值得特性后,可直接再if(poll.val == a) list.add(poll);这句后return poll;  以下代码懒得改了
	 * 
	 * 查找个插入很相似,还有其他方式,也可用简单的代码实现,这里这就不详细说了
	 */
	public void find(TreeNode node , int a,List<TreeNode> list){
		Queue<TreeNode> queue = new LinkedList<>();
		queue.offer(node);
		while(!queue.isEmpty()){
			int size = queue.size();
			for(int i=0;i<size;i++){
				TreeNode poll = queue.poll();
				if(poll.val == a) list.add(poll);
				if(poll.leftNode != null){
					queue.offer(poll.leftNode);
				}
				if(poll.rightNode != null){
					queue.offer(poll.rightNode);
				}
			}
		}
	}
		
	/**
	 * 普通查找节点
	 * @param node
	 * @param a
	 * @return
	 */
	public TreeNode find2(TreeNode node,int a){
		if(node != null){
			if(node.val < a) node = find2(node.rightNode, a) ;
			if(node.val > a) node = find2(node.leftNode, a) ;
		}else {
			return null;
		}
		return node;
	}
	
	/**
	 * 查找最小值,因为最小值是肯定没有右子树的
	 * 查找最大值同理
	 * @param node
	 * @return
	 */
	public TreeNode min(TreeNode node) {
		if(node == null) return null;
		while(node.leftNode !=null ){
			node = node.leftNode;
		}
		return node;
	}
	
	/**
	 * 删除某个节点,这里分为三种情况
	 * 1.该节点没有左右子树,删除节点之后不影响树结构
	 * 2.该子节点只有左子树PL或右子树PR,只需要让PL或者RL成为该节点的父节点的RL或者PL即可,不改变搜索树的特性
	 * 3.若该结点P的左子树和右子树均不空。在删去p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,
	 *   即先用P节点右子树的最小数据替换该结点,然后递归地删除那个最小数据的结点(这个最小数据结点一定是没有左孩子的)
	 * @param treeNode
	 * @param a
	 */
	public TreeNode delete(TreeNode node, int a) {
		if (node != null) {
			// 这下面两步是为了查找到a的节点
			if (node.val < a) {
				node.rightNode = delete(node.rightNode, a);
			} else if (node.val > a) {
				node.leftNode = delete(node.leftNode, a);
			} else if (node.val == a) {
				if (node.leftNode == null && node.rightNode == null && node.val == a) {
					return node = null;
				}else if (node.leftNode != null && node.rightNode == null) {
					return node.leftNode;
				}else if (node.leftNode == null && node.rightNode != null) {
					return node.rightNode;
				}else if (node.leftNode != null && node.rightNode != null) {
					// 找出右子树中的最小值
					TreeNode node2 = min(node.rightNode);
					// 将最小值赋予node
					node.val = node2.val;
					// 删除node2节点
					node.rightNode = delete(node.rightNode, node2.val);
					return node;
				}
			}
		} else {
			return node;
		}
		return node;
	}
	
	public static void main(String[] args) {
		int[] a = {32,18,40,9,28,65,12,12,29,56,87};
//		int[] a = {32,18,40,9,28,65,12,12,29,56,87,1,2,3,4};
		BSTDemo demo = new BSTDemo();
		TreeNode bstInsert = demo.BSTInsert(a);
//		System.out.println(demo);
		
		List<TreeNode> list = new ArrayList<>();
		demo.find(bstInsert,28, list);
		for(TreeNode tn : list){
			System.out.println(tn);
			System.out.println(tn.val);
		}
		
		TreeNode find2 = demo.find2(bstInsert,0);
		if(find2 == null){
			System.out.println("没有找到");
		}else {
			System.out.println(find2.val);
		}
		
		System.out.println(demo.min(bstInsert).val);
		
		TreeNode delete = demo.delete(bstInsert, 18);
		System.out.println(delete);
	}
}

下面上图
这是第一个数组生成的bst树
在这里插入图片描述
删除18节点过程
在这里插入图片描述
假设18节点为P
首先遍历节点P的右子树,得到最小的值为28,此时将节点P的val改为28,然后删除P的右子树,让右子树指向29

删除18节点后
在这里插入图片描述

有不对的地方望大家指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值