说在前面

如题目所言

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

符号表

含义

是一个键和一个值联系起来是它的目的,用例可以插入一对键值入表,也可以按键索值,可以按照地图去理解:键就是坐标,地点就是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. 用 wait-notify 写一段代码来解决生产者-消费者问题?(答案)

    请参考答案中的示例代码.只要记住在同步块中调用 wait() 和 notify()方法,如果阻塞,通过循环来测试等待条件.

  2. 抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized 修饰?

    都不能.抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛 盾的.本地方法是由本地代码(如 C 代码)实现的方法,而抽象方法是没有实现 的,也是矛盾的.synchronized 和方法的实 ...

  3. 快速注册service服务

    一.通过SpringContextHolder的getBean来注册service服务 导入的包:import com.bessky.platform.context.SpringContextHol ...

  4. 树莓派系统安装(ubuntu版本)无需屏幕

    0.前提 所需物品:一个手机.一台电脑.一个树莓派.一张tf卡和一个读卡器.所需软件:Win32DiskImager.putty还需要ubuntu系统镜像源.这些我都放在百度网盘上了链接:https: ...

  5. 3_Phase Portrait_相图_相轨迹

  6. Web最佳实践阅读总结(1)

    介绍 最近开始刷一些书和题,此系列是介绍在读Web最佳实践的一些收获和体会. web前端发展现状 存在问题: 代码组织混乱 代码格式的问题突出 页面布局随意 网站整体性能差,没有意识到应用诸如缓存,动 ...

  7. 如何利用WebSocket实现网页版聊天室

    花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...

  8. 【Weex笔记】-- Animate.css的使用

    animate.css是一个使用CSS3的animation制作的动画效果的CSS集合,里面预设了很多种常用的动画,且使用非常简单.本文将详细介绍animate.css的使用. 一,安装辅助依赖 np ...

  9. C++中的算法头文件<algorithm>,<numeric>和<functional>

    算法部分主要由头文件<algorithm>,<numeric>和<functional>组成.<algorithm>是所有STL头文件中最大的一个,它是 ...

  10. 调试了一个早上, 定位了一个chrome的新问题, 新版chrome 不能有效的追踪客户来源Referer了