算法之树(二,B+树、哈夫曼树、堆、红黑树)(Java版)-持续更新补充

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: B+树的优势 1.单一节点存储更多元素。B+树中间节点没有卫星数据(也就是说只包含索引信息),所以每个非叶子节点可以包含更多的内容,同样大小的磁盘页可以容纳更多的节点元素。也就是说B+树会在相同数据量的情况下比B树更加“矮胖”,查询的IO次数更少。

接着来搞树!

支持云栖社区,也希望大家能支持下我的独立博客——白水东城
文章地址:
算法之树(二,B+树、哈夫曼树、堆、红黑树)(Java版)-持续更新补充

一、B+树

B+树的特征

  1. 有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点
  2. 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接
  3. 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素
    如图(图片来自程序员小灰)

此处输入图片的描述

在程序员小灰的公众号里提到了一个概念——卫星数据:索引元素指向的数据记录,比如数据库中的某一行。在B+树中只有叶子节点带卫星数据,其他的中间节点只是索引,没有任何数据关联。在数据库的聚集索引(Clustered Index)中,叶子节点直接包含卫星数据。在非聚集索引(NonClustered Index)中,叶子节点带有指向卫星数据的指针。 吧

B+树的优势

  1. 单一节点存储更多元素。B+树中间节点没有卫星数据(也就是说只包含索引信息),所以每个非叶子节点可以包含更多的内容,同样大小的磁盘页可以容纳更多的节点元素。也就是说B+树会在相同数据量的情况下比B树更加“矮胖”,查询的IO次数更少。
  2. 查询效率稳定。B+树的查询必须最终找到叶子节点,而B树如果在中间节点找到匹配的即可(最好情况是只查根节点,最差是查到叶子节点),而B+树每一次都是稳定的。B-树的好处是,虽然查询性能不稳定,但平均的查询速度快一些。试想一个数据库的查询,有时候执行10毫秒,有时候执行100毫秒,肯定是不太合适的。还不如每次都执行30毫秒。
  3. 范围查询简便。B树的范围查询只能依靠繁琐的中序遍历,找到下限和上限。而B+树的范围查询很简单,只需要在叶子节点那一层的链表上做遍历就行

为什么数据库中一定要索引

二分查找,二叉树查找都依赖特定的数据结构,分别是待查找数据有序、二叉查找树,显然数据本身不能完全满足各种数据结构。
所以,数据库除了维护数据之外,还维护者满足特定查找算法的数据结构——索引,索引以某种方式引用数据,这样就可以在索引的基础上实现高级的查找等操作。目前大部分数据库系统和文件系统都采用B树或者变种的B+树来作为索引结构

为什么MySQL数据库中使用B+树

1.局部性原理与磁盘预读
由于磁盘的存取速度与内存之间鸿沟,为了提高效率,要尽量减少磁盘I/O.磁盘往往不是严格按需读取,而是每次都会预读,磁盘读取完需要的数据,会顺序向后读一定长度的数据放入内存。而这样做的理论依据是计算机科学中著名的局部性原理:

当一个数据被用到时,其附近的数据也通常会马上被使用,程序运行期间所需要的数据通常比较集中

由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率.预读的长度一般为页(page)的整倍数。

2.数据库索引采用B+树的主要原因
根据上面的局部性原理和磁盘预读,B树中用了这个技巧:每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个结点只需一次I/O。
B树在提高了IO性能的同时并没有解决元素遍历的效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁(比如查询某段时间之内的数据)的,而B树不支持这样的操作或者说效率太低(前文已经说明效率低的原因)。

二、哈夫曼树

带权路径长度最小的树就叫最优二叉树,也就是哈夫曼树。要使带权路径长度最小,那么权值大的点就应该离根节点越近。
构造方法:先从小到大排序,然后选择最小的两棵树合并,重复这两个步骤。

哈夫曼编码

如果对一段英文转换为二进制传输,采用哈夫曼编码,让频率高的用短码,频率低的用长码,而且保证不会有某个字符的串是另一个字符的前缀(因为如果每个字符的长度不一样会出现这样的问题,比如,一个字符被11表示,另一个被110表示,出现一段11011,这样就有歧义)

哈夫曼树实现

之前数据结构课上用C写过哈夫曼树,Java的暂时不搞了,之后遇见再回来补充。

三、堆

堆是一个完全二叉树,大顶堆就是每个节点都不大于它的父节点。
插入和删除时间复杂度都是O(logn)。

堆排序

初始化一个堆,然后把无序数组的每个值都依次插入堆中,然后一直删除,把被删除的元素放到数组的最后一个有效元素之后的位置。

public class Heap {
    private int[] element;
    
    public Heap(int maxSize) {
        element = new int[maxSize];
        element[0] = 0;//存放堆中实际的个数
    }
    
    public boolean isEmpty() {
        return element[0] == 0;
    }
    public boolean isFull() {
        return element[0] == element.length - 1;
    }
    public void insert(int value) {
        if(isFull()) {
            throw new IndexOutOfBoundsException("堆已经满啦..");
        }
        if(isEmpty()) {
            element[1] = value;
        }else {
            int i = element[0] + 1;
            while(i != 1 && value > element[i / 2]) {
                element[i] = element[i / 2];
                i /= 2;
            }
            element[i] = value;
        }
        element[0] ++;
    }
    public int delete() {
        if(isEmpty()) {
            throw new IndexOutOfBoundsException("堆空啦");
        }
        int deleteElement = element[1];
        element[1] = element[element[0]];
        element[0]--;
        int value = element[1];
        int parent = 1;
        int child = 2;
        while(child <= element[0]) {
            if(child + 1 <= element[0] && element[child] < element[child + 1]) {
                child ++;
            }
            if(value >= element[child]) {
                break;
            }else {
                element[parent] = element[child];
                parent = child;
                child *= 2;
            }
        }
        element[parent] = value;
        return deleteElement;
    }
    public void printAll() {
        for(int i = 0; i < element[0]; i++) {
            System.out.print(element[i]);
            if(i != element[0]) {
                System.out.print(",");
            }
        }
        System.out.println();
    }
    public void sort() {
        int size = element[0];
        for(int i = 0; i < size; i++) {
            int deleteElement = delete();
            element[element[0] + 1] = deleteElement;
        }    
        for(int i = 1; i <= size; i++) {
            System.out.print(element[i]);
            if(i != size) {
                System.out.print(",");
            }
        }
    }
}

红黑树

红黑树的插入、删除、查找最坏时间复杂度都是O(logn)。
红黑树理解概念就OK了,目前不深入研究。
推荐一篇很好的对红黑树的概念理解文章:
漫画:什么是红黑树?

文章地址:
算法之树(二,B+树、哈夫曼树、堆、红黑树)(Java版)-持续更新补充
参考

  1. 《轻松学算法》赵烨
  2. 漫画:什么是B+树?
  3. 为什么MySQL数据库索引选择使用B+树?
  4. 数据库为什么要用B+树结构--MySQL索引结构的实现
  5. 由 B-/B+树看 MySQL索引结构
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
算法 C++
【数据结构与算法】—— 手撕红黑树
【数据结构与算法】—— 手撕红黑树
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--希尔排序
数据结构与算法(Java篇)笔记--希尔排序
|
12天前
|
机器学习/深度学习 算法 搜索推荐
Machine Learning机器学习之决策树算法 Decision Tree(附Python代码)
Machine Learning机器学习之决策树算法 Decision Tree(附Python代码)
|
25天前
|
机器学习/深度学习 算法 数据挖掘
请解释Python中的决策树算法以及如何使用Sklearn库实现它。
决策树是监督学习算法,常用于分类和回归问题。Python的Sklearn库提供了决策树实现。以下是一步步创建决策树模型的简要步骤:导入所需库,加载数据集(如鸢尾花数据集),划分数据集为训练集和测试集,创建`DecisionTreeClassifier`,训练模型,预测测试集结果,最后通过`accuracy_score`评估模型性能。示例代码展示了这一过程。
|
27天前
|
机器学习/深度学习 算法
随机森林算法是如何通过构建多个决策树并将它们的预测结果进行投票来做出最终的预测的?
【2月更文挑战第28天】【2月更文挑战第102篇】随机森林算法是如何通过构建多个决策树并将它们的预测结果进行投票来做出最终的预测的?
|
19天前
|
存储 算法 Java
Java数据结构与算法-java数据结构与算法(二)
Java数据结构与算法-java数据结构与算法
60 1
|
14天前
|
搜索推荐 Java
Java排序算法
Java排序算法
17 0
|
14天前
|
搜索推荐 Java
Java基础(快速排序算法)
Java基础(快速排序算法)
21 4
|
17天前
|
存储 算法 JavaScript
Java入门高频考查算法逻辑基础知识3-编程篇(超详细18题1.8万字参考编程实现)
解决这类问题时,建议采取下面的步骤: 理解数学原理:确保你懂得基本的数学公式和法则,这对于制定解决方案至关重要。 优化算法:了解时间复杂度和空间复杂度,并寻找优化的机会。特别注意避免不必要的重复计算。 代码实践:多编写实践代码,并确保你的代码是高效、清晰且稳健的。 错误检查和测试:要为你的代码编写测试案例,测试标准的、边缘情况以及异常输入。 进行复杂问题简化:面对复杂的问题时,先尝试简化问题,然后逐步分析和解决。 沟通和解释:在编写代码的时候清晰地沟通你的思路,不仅要写出正确的代码,还要能向面试官解释你的
32 0
|
19天前
|
XML 存储 算法
Java数据结构与算法-java数据结构与算法(五)
Java数据结构与算法-java数据结构与算法
47 0