说在前面

如题目所言

这篇文章为了给下一篇二叉查找数做铺垫和前期知识准备,以便大家有良好的阅读体验,本来想合在一起的,但觉得有些长,所以就拆开了哈哈哈,还是新手向,两篇文章有些长,但如果能认真看下去,实操踩一遍,我认为新手对二叉树的代码实现和基础知识这块,就没什么问题了。当然如果有大佬赐教留言则洗耳恭听哈哈。

符号表

含义

是一个键和一个值联系起来是它的目的,用例可以插入一对键值入表,也可以按键索值,可以按照地图去理解:键就是坐标,地点就是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实现)的更多相关文章

  1. 2015最新iherb海淘攻略-图文入门教程

    IHerb是美国最热门的海淘海购网站之中的一个,适合不爱担心,怕麻烦的朋友入门海淘,由于它有中文页面,可直邮中国,上千个母婴用品.化妆品.保健品品牌,最重要的是!首次下单,价值$40及以上的订单会马上 ...

  2. 2015最新iherb海淘攻略-图文入门教程-6月免邮

    注:仅仅有首次下单才享有新人优惠10$,大家下单之后千万不要取消后.否则之后则不享有新人优惠. 注:眼下Sino-海淘客国际物流已取消,仅有UCS合众速递. IHerb是美国最热门的海淘海购网站之中的 ...

  3. Stick hero "攻略", android 代码编写与分析(后台截屏, 后台模拟点击)

    论文写完,感觉头脑好久没被灵感刺激了,前些天室友介绍了个小游戏,我突然来了灵感可以写的简单的android 程序实现自动运行.主要的过会为三步: 1,Android 屏幕的获取.因为安全的原因,过程比 ...

  4. "二分法"-"折半法"-查找算法-之通俗易懂,图文+代码详解-java编程

    转自http://blog.csdn.net/nzfxx/article/details/51615439 1.特点及概念介绍 下面给大家讲解一下"二分法查找"这个java基础查找 ...

  5. 折半插入排序 之通俗易懂,图文+代码详解-java编程

    转自http://blog.csdn.net/nzfxx/article/details/51615439 1.特点及概念介绍 下面给大家讲解一下"二分法查找"这个java基础查找 ...

  6. Windows英文版GitHub客户端使用操作流程图文攻略教程现没中文版

    Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理.作为一个程序员,我们需要掌握其用法. 作为开源代码库以及版本控制系统,Github目前拥有140 ...

  7. GitHub超详细图文攻略

    GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git 分类: 转载2014-03-25 21:10 10641人阅读 评论(2) 收藏 举报 GitHubbr ...

  8. 【转载】Google Analytics 使用图文全攻略

    转载自:Google Analytics 使用图文全攻略 最近一段时间,因为工作的需要,小励使用GA(GA是Google Analytics的简称)比较频繁,所以花时间研究了一下,从不太了解到会使用( ...

  9. 逗塔战争TD新人入门图文攻略

    逗塔战争TD新人入门图文攻略   <逗塔战争TD>是一张基于DOTA改编的塔防TD,很多玩家都很喜欢这张图,新手玩家怎么快速上手这张图呢?这张图的玩法和基本规则并不难,下面就为大家带来新人 ...

随机推荐

  1. Oracle :value too large for column "SCHEMA"."TABLE"."COLUMN" (actual: 519, maximum: 500)的解决方案

    原因:我是使用 CREATE TABLE XXX AS subquery 进行创建的数据表,主要是将相关的数据聚合在一起,然后通过导出为SQL脚本文件,进行导入到新库中,导致部分INSERT INTO ...

  2. 为什么使用 Executor 框架比使用应用创建和管理线程好?

    为什么要使用 Executor 线程池框架 1.每次执行任务创建线程 new Thread()比较消耗性能,创建一个线程是比较耗 时.耗资源的. 2.调用 new Thread()创建的线程缺乏管理, ...

  3. jpa CriteriaQueryNo explicit selection and an implicit one could not be determined

    java.lang.IllegalArgumentException: Error occurred validating the Criteria ... Caused by: java.lang. ...

  4. spring boot 自动装配的原理

    参考: https://blog.csdn.net/Dongguabai/article/details/80865599.如有侵权,请联系本人删除! 入口: import org.springfra ...

  5. 微信小程序中涉及虚拟产品购买,ios暂不支持的相关整理意见

    这个东西呢也不能怪微信小程序,属实苹果搞的事情,那怎么小程序相关内容去通过审核呢? 首先我们要搞清楚哪些属于虚拟商品:如某某书币,某某会员,或者是提前编辑好的网课,文档等都属虚拟商品购买,简言之就是没 ...

  6. IOS动态调试汇总-傻瓜版教程

    参考博客: https://juejin.cn/post/6872764160640450574#heading-4 (断点后续指令) https://www.jianshu.com/p/67f08a ...

  7. 5. Git初始化及仓库创建和操作

    4. Git初始化及仓库创建和操作 基本信息设置 1. 设置用户名 git config --global user.name 'itcastphpgit1' 2. 设置用户名邮箱 git confi ...

  8. 推荐一个用于压缩图片的JS插件:localResizeIMG

    惯例,先贴传送门:https://github.com/think2011/localResizeIMG 首先说到,为嘛要压缩图片,这需求一般出现在需要上传照片(尤其是移动端)的情况下,现在手机拍出来 ...

  9. canvas绘图API详解

    canvas绘图API详解 1.context的状态 矩阵变换属性 当前剪辑区域 context的其他状态属性: strokeStyle, fillStyle, globalAlpha, lineWi ...

  10. 从零到有模拟实现一个Set类

    前言 es6新增了Set数据结构,它允许你存储任何类型的唯一值,无论是原始值还是对象引用.这篇文章希望通过模拟实现一个Set来增加对它的理解. 原文链接 用在前面 实际工作和学习过程中,你可能也经常用 ...