关于二叉排序(查找/搜索)树(BST)的总结以及Java实现查找插入删除

首先告诉大家我写这篇博客的目的,大三寒假在家准备CCF,想着先复习一下基础的数据结构,但是一个人自学实在是比较难以坚持,你懂的,前几天在看软考相关的文章时看到一个思想觉得很好:以考促学。那我就以写博客促学吧!

在这篇文章之后,会写一下 二叉排序树(BST) 的改进(平衡二叉树等),因为任何算法都不是完美的。

本篇博客的内容
BST的定义;插入;查找;删除

行文中一些素材来源:
https://www.cnblogs.com/Kiven5197/p/8877177.html
https://blog.csdn.net/isunbin/article/details/81703762
大家也可以去看看这两篇,流程图片比较详细

如何汲取本博客:
在阅读之前要想一想自己想要弄明白什么,自己的困惑是什么(对一般人来说是删除)
各取所需,重点有加粗标注

0 为什么要引入二叉排序树

既然有了线性存储排序算法(顺序存储和链式存储),为什么还要引入bst?
肯定是因为有不足啊,其实各种排序算法各有优缺点,适用于不同场合。
下面聊聊不足

  1. 顺序存储
    无序的:查找插入删除都困难
    有序的:可以二分查找,效率还行,但插入删除可能会造成大量数据移动,导致效率不高
  2. 链式存储
    插入删除还可,但无论是否排序,查找操作都比较麻烦,需要从头向后对比

1 定义

要点:左<根<右
一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。
也就是说,左<根<右,如下图:
在这里插入图片描述

2 二叉排序树的创建与插入

创建要点:二叉排序树类要包含一个根节点
插入要点:大放右,小放左
创建与插入过程如下图所示:
要点:若二叉树为空,则首先单独生成根节点;新插入的节点总是叶子节点
在这里插入图片描述

3 二叉排序树的查找

要点:递归(其实树这种数据结构,很多地方都用到了递归)
步骤:

  1. 若根结点的值等于查找的值,成功。
  2. 若小于根结点的值,递归查左子树。
  3. 若大于根结点的值,递归查右子树。
  4. 若子树为空,查找不成功。

代码如下:

	public Node search(int value) {
		if(this.value==value) {
			return this;
		}else if(value<this.value) {
			if(left==null) {
				return null;
			}
			return left.search(value);
		}else{
			if(right==null) {
				return null;
			}
			return right.search(value);
		}
	}

4 二叉排序树节点的删除

先说:删除就是指针置空
这才是二叉排序树中最重要的部分,说重要是因为相比于查找和插入,节点删除是比较麻烦的,有三种情况
不过复杂一点才能更好地锻炼数据结构与算法思维
下面分情况讨论
4.1 叶子节点的删除(直接删除)

  1. 该叶子节点也是根节点(这是一颗只有一个节点的二叉树),将该节点指针置为null即可
  2. 将父节点连接该删除节点的指针置空即可
//parent指的是该节点的父节点
//要删除的节点是父节点的左子节点
if(parent.left.value==value) {
	parent.left=null;
//要删除的节点是父节点的右子节点
}else {
	parent.right=null;
}

4.2 只有左子树或只有右子树的树节点的删除(上移子树)

				//有左子节点
				if(target.left!=null) {
					//要删除的节点是父节点的左子节点
					if(parent.left.value==value) {
						parent.left=target.left;
						//要删除的节点是父节点的右子节点
					}else {
						parent.right=target.left;
					}
				//有右子节点
				}else {
					//要删除的节点是父节点的左子节点
					if(parent.left.value==value) {
						parent.left=target.right;
						//要删除的节点是父节点的右子节点
					}else {
						parent.right=target.right;
					}
				}

4.3 既有左子树也有右子树的树节点的删除(用AB两个树节点之一来替换当前节点,然后调整树结构)
也就是说,用当前节点的左子树中值最大的节点(A)替换当前节点,或者用当前节点的右子树中值最小的节点(B)替换当前节点。然后调整树结构(说是调整树结构,其实搜索到A(B)后 删除 A(B)就可以了,因为删除本身就会调整,也就是会重新分三种情况删除)

if(target.left!=null&&target.right!=null) {
	//删除右子树中值最小的节点,获取到该节点的值(或者删除左子树中值最大的节点)
	int min = deleteMin(target.right);
	//替换目标节点中的值
	target.value=min;
}	

其中deleteMin函数的作用是删除右子树中值最小的节点
下面给出该函数代码:

	private int deleteMin(Node node) {
		Node target = node;
		//递归向左找
		while(target.left!=null) {
			target=target.left;
		}
		//删除最小的这个节点
		delete(target.value);
		return target.value;
	}

总结

二叉排序树整挺好
如果有需求,之后会更新一下把整个源码链接贴在下面,祝各位精通算法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值