二叉查找树速通攻略 图文代码精心编写(Java实现)
说在前面
如题目所言
这篇文章为了给下一篇二叉查找数做铺垫和前期知识准备,以便大家有良好的阅读体验,本来想合在一起的,但觉得有些长,所以就拆开了哈哈哈,还是新手向,两篇文章有些长,但如果能认真看下去,实操踩一遍,我认为新手对二叉树的代码实现和基础知识这块,就没什么问题了。当然如果有大佬赐教留言则洗耳恭听哈哈。
符号表
含义
是一个键和一个值联系起来是它的目的,用例可以插入一对键值入表,也可以按键索值,可以按照地图去理解:键就是坐标,地点就是value,概念很简单
分类
有序;无序 ,他们的区别可以暂时粗略认为他们的key前者可以比较,后者则不可
符号表实现方式&二叉查找树的引出
- 链表,数组都可以,前者的实现具有不错的插入性能表现;后者更易于查找,有下标嘛因为,链表的话只能从头遍历,耗时完全取决于输入的目标查找和链表已有长度(计算机硬件性能就不再讨论范围了哈)。
- 但是这两种在面对海量查找和巨大符号表时候,表现糟糕,所以人们就把链表的插入优势和数组的结合,发明了二叉差查找树的数据结构。
好既然说到了树,简单把树的分类大致一说
树tree
- 定义
一种抽象数据结构 - 特点
1.有限节点
2.分层
3.节点之间用链接连接
4.几个术语:度、叶子节点、根结单、父节点、深度高度.....
基本见名知意,个别有不了解的读者可自行百度 - 分类
1.二叉树 :
图我画的有些丑大家看个意思,懂我说啥就行哈
满二叉树:简单理解就是没有空链接,所以满二叉树一定是完全二叉树

完全二叉树:最后一层从左到右的叶子结点一定要连续,中间不能有空余
第一种:

第二种

但是下面这个就不是完全二叉树,因为最下面一层从左到右叶子节点不连续

2.动态查找树:
二叉查找数(二叉树的衍生品);平衡二叉查找数(2-3树 ,红黑树);哈夫曼树
这些就是我下一篇重点和大家聊的
3.多路查找数 B树;B+树;B* 树 ,R树(这些就属于‘图’了)
二叉树之二叉查找树
好现在回来,符号表就是二叉树这些东西的预备知识,下面聊二叉查找树
下面的图从左到右表示各种树之间的一种递进关系,或者说右边的是由左边的改造增强而来,并不是包含关系

二叉树
- 基本构成元素:
1.结点,每个节点包含一个键key一个值value,每个节点都只有左右两个链接;分别指向左右节点。
2.链接(允许空链接,单不允许为空键),每个链接都指向一个独立的二叉树
二叉查找树
描述
在二叉树的基础上让键有序允许空键,各子树和他们的父节点的键之间的关系:每个节点的键都大于它左子树任意节点的键而小于右子树任意节点的键
代码实现 ,注释写的很明白,就不过多废话了
点击查看代码
package Tree;
/**
* @author HuiJixu
* @version 2.0
* @since 2021.9
*/
public class BST<Key extends Comparable<Key> ,Value>{
//BST's root node
private Node root;
//定义节点的结构
private class Node{
private Key key ;
private Value value ;
private Node left ,right ; //指向该节点的子树的左右链接
private int N ; //该接待你所包含的节点数目
//节点构造器
public Node(Key key , Value value , int N){
this.key = key ;
this.value = value ;
this.N = N;
}
public int size(){return size(root) ;}
public int size(Node x ){
if (x == null){
return 0 ;
}else{
return x.N;
}
}
//按键索值
//这个方法是暴露给用例的方法
public Value get(Key key){
return get(root , key);
}
//像这种不暴露给用例的方法就要做个封装
private Value get(Node node, Key key){
//在以root为根节点的树中查找并返回key对应的值,没有就null
if (node == null ) return null ;
//不为空就比较,类似二分法查找
int temp = key.compareTo(node.key);
if ( temp < 0 ) return get(node.left,key); //将当前节点的左子节点作为新根节点继续往下查找
else if( temp > 0 ) return get(right.right,key); //将右子树根节点作为新根节点
else return node.value;
}
public void put(Key key , Value value){
//先查找key,有key则更新,没有就新建节点
root = put( root , key ,value );
}
private Node put(Node node, Key key , Value value ){
//找不到key说明是新键,那就new 并插入该子树中
if(node == null) return new Node(key,value,1) ; //最新的叶子节点只含所有自己一个节点
//key存在在以当前node为根节点的子树中,就更新它的值
int temp = key.compareTo(node.key);
if( temp < 0 ) node.left = put(node.left ,key ,value );
else if( temp > 0 ) node.right = put(node.right ,key , value ) ;
else node.value = value ;
//更新所含有的节点数目
node.N = size(node.left) + size(node.right) + 1 ;
return node;
}
//delete() 单独说这个方法先把代码放在这里
public void delete(Key key){
root = delete(root ,key);
}
//在delete操作中,要找出右子树中的最小键对应的value ,并将其作为新的根节点,而作为原先地方的节点就要珊瑚了
public void deleteMin(){
root = deleteMin(root);
}
public Node deleteMin(Node node){
//不断检索左子树,直到遇见空节点,则说明该节点就位最小的
if ( node.left == null) return node.right;
//不是空的话就继续递归查找左子树
node.left = deleteMin(node.left);
//更新节点
node.N = size(node.right)+ size(node.left) + 1 ;
return node;
}
private Node delete(Node node , Key key ){
//空的就直接返回
if (node == null) return null ;
//二分查找非空 .递归查找
int temp = key.compareTo(node.key);
if( temp < 0 ) node.left = delete(node.left , key);
else if( temp > 0 ) node.right = delete(node , key);
//找到了就删除
else {
//下一个是空的返回另一边
if( node.left == null) return node.right ;
else if ( node.right == null) return node.right ;
//两边都不为空
Node t = node ; // 保存指向即将被删除的节点的链接
t = min(node.right); //将该链接重新指向要被删除的节点的后继节点(下文解释后继节点)
node.right = deleteMin(t.right); //将要被删除的节点指向删除后仍然所有节点都大于node.key的 //子二叉树,保证树的有序性不变
node.left = t.left ; // 左链接保持一致
}
//更新删除后节点所含有子节点数
node.N = size(node.left) + size(node.right) + 1 ;
return node ;
}
//返回最小值的节点的键
// 其实这样的话如果root节点过高的话,查询效率会首先与树的深度
public Key min(){
return min(root).key;
}
private Node min(Node node){
if (node.left == null) return node ;
return min(node.left) ;
}
}
}
二叉查找树的delete()方法
- 分析
为了方便叙述,我们约定被删除的节点记为node ,其左节点为node.left ; 右节点为node.right ,记指向node的链接为t
要删除一个节点,三件事:1.删除node 2. 将被node的左右子树父节点更新 3.更新该树的相关路径上的节点所包含的子节点个数
把1和2和起来考虑其实就是把node留下的坑填上,有两个方法一种思路:method1:在左子树找出最大的前置节点;method2:在右子树中找出最小后置节点。两者都是为了保持树的有序性。这里代码选择method1,那么就需要一个找出最小节并将其在原位置删除并且返回该最小节点的方法,实现思路就是一直沿着左子树找直到null;代码在上面名为deleteMin(Node node)。 - 实现步骤 ,我图画的是丑了写,但是意思到了哈
初始状态

1、保存指向 node 链接 t

2、将node 指向它的后继节点

3、将node的右链接指向删除后仍然都大于node.key的子二叉树

4、将node的左链接设为 t.left

整理不易,觉得还不错不妨点个赞在走嗷!
平衡二叉查找树在下一篇文章
二叉查找树速通攻略 图文代码精心编写(Java实现)的更多相关文章
- 2015最新iherb海淘攻略-图文入门教程
IHerb是美国最热门的海淘海购网站之中的一个,适合不爱担心,怕麻烦的朋友入门海淘,由于它有中文页面,可直邮中国,上千个母婴用品.化妆品.保健品品牌,最重要的是!首次下单,价值$40及以上的订单会马上 ...
- 2015最新iherb海淘攻略-图文入门教程-6月免邮
注:仅仅有首次下单才享有新人优惠10$,大家下单之后千万不要取消后.否则之后则不享有新人优惠. 注:眼下Sino-海淘客国际物流已取消,仅有UCS合众速递. IHerb是美国最热门的海淘海购网站之中的 ...
- Stick hero "攻略", android 代码编写与分析(后台截屏, 后台模拟点击)
论文写完,感觉头脑好久没被灵感刺激了,前些天室友介绍了个小游戏,我突然来了灵感可以写的简单的android 程序实现自动运行.主要的过会为三步: 1,Android 屏幕的获取.因为安全的原因,过程比 ...
- "二分法"-"折半法"-查找算法-之通俗易懂,图文+代码详解-java编程
转自http://blog.csdn.net/nzfxx/article/details/51615439 1.特点及概念介绍 下面给大家讲解一下"二分法查找"这个java基础查找 ...
- 折半插入排序 之通俗易懂,图文+代码详解-java编程
转自http://blog.csdn.net/nzfxx/article/details/51615439 1.特点及概念介绍 下面给大家讲解一下"二分法查找"这个java基础查找 ...
- Windows英文版GitHub客户端使用操作流程图文攻略教程现没中文版
Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理.作为一个程序员,我们需要掌握其用法. 作为开源代码库以及版本控制系统,Github目前拥有140 ...
- GitHub超详细图文攻略
GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git 分类: 转载2014-03-25 21:10 10641人阅读 评论(2) 收藏 举报 GitHubbr ...
- 【转载】Google Analytics 使用图文全攻略
转载自:Google Analytics 使用图文全攻略 最近一段时间,因为工作的需要,小励使用GA(GA是Google Analytics的简称)比较频繁,所以花时间研究了一下,从不太了解到会使用( ...
- 逗塔战争TD新人入门图文攻略
逗塔战争TD新人入门图文攻略 <逗塔战争TD>是一张基于DOTA改编的塔防TD,很多玩家都很喜欢这张图,新手玩家怎么快速上手这张图呢?这张图的玩法和基本规则并不难,下面就为大家带来新人 ...
随机推荐
- Listener是什么?有什么作用?
Listener是指Servlet中的监听器. Listener可以对ServletContext对象.HttpSession对象.ServletRequest对象进行监听.
- 详细描述一下 Elasticsearch 搜索的过程?
想了解 ES 搜索的底层原理,不再只关注业务层面了. 解答: 搜索拆解为"query then fetch" 两个阶段. query 阶段的目的:定位到位置,但不取. 步骤拆解如下 ...
- Dubbo 的整体架构设计有哪些分层?
接口服务层(Service):该层与业务逻辑相关,根据 provider 和 consumer 的 业务设计对应的接口和实现 配置层(Config):对外配置接口,以 ServiceConfig 和 ...
- 设计一个简单的devops系统
前言 公司设计的RDMS挺好用的,我也照猫画虎简单的设计一个DevOps系统,与大家分享,不足之处欢迎拍砖,以免误人子弟 前置条件 gitlab gitlab-runner k8s 1. gitlab ...
- 错误问题之“Apache Log4j 漏洞,在版本为包含2.14以内!”
漏洞概述 Apache Log4j是一个用于Java的日志记录库,其支持启动远程日志服务器. Log4j 1.2 中包含一个 SocketServer 类,该类容易受到不可信数据反序列化的影响,当侦听 ...
- L298N双H桥集成电路板的双H桥是什么意思?为什么要叫双H桥?L298N工作原理
H桥是一个典型的直流电机控制电路,因为它的电路形状酷似字母H,故得名与"H桥".4个三极管组成H的4条垂直腿,而电机就是H中的横杠. 控制两个三极管的导通来控制电流方向,从而实现电 ...
- ES6实战:新数字方法
本文翻译自:https://www.sitepoint.com/es6... 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 本文介绍了ES6中全新的数字方 ...
- 驳《我不是很懂 Node.js 社区的 DRY 文化》
今天在群里有人讨论方老师的文章<我不是很懂 Node.js 社区的 DRY 文化>,我也看了一遍,槽点太多,不知道如何下笔. 方老师分析了几个依赖最多的 npm 包,每个都只有不到百行代码 ...
- 【Android开发】URL[] 转成 bitmap[]
public static Bitmap[] getBitmapFromURL(String[] path) throws MalformedURLException { Bitmap[] b = n ...
- Java中JSONArray转换成int[]的办法
今天写项目的时候要做一个MyBatis的带IN子句的删除,于是用一个整型数组来保存待删除数据的ID 从前端将JSON字符串搞过来之后如何将JSONArray转换成int类型数组就成了个问题 下面是我的 ...