【数据结构篇】数据结构中的 R 树和 B 树

在这里插入图片描述

数据结构中的 R 树和 B 树

  • ✔️关于R树(RTree)
  • ✔️什么是B树(B-tree)
    • ✔️B树和B+树的区别
    • ✔️B树和B+树在数据存储方面的具体差异
  • ✔️拓展知识仓
    • ✔️R树和B树的区别
    • ✔️ 那在内存消耗上有什么区别?
    • ✔️ R树有哪些优点和缺点


✔️关于R树(RTree)


1. 定义与结构:
R树是一种多维空间索引数据结构,用于高效地存储和检索空间数据。它通过将空间划分为多个子区域,并将数据点或对象分配给相应的区域来工作。每个区域都由树的一个节点表示,树的叶节点包含空间对象。


2. 区域划分:
R树按照一定规则将空间划分为一系列不重叠的矩形区域,每个节点代表一个区域。根据需要,空间可以继续划分为更小的子区域,从而形成树的分支。树的最底层叶节点包含空间中的点或对象。


3. 插入与删除操作:
当向R树中插入新的空间对象时,算法会根据对象的位置将其分配给适当的叶节点或创建新的叶节点。如果新对象导致现有叶节点超出其区域范围,则该叶节点会分裂成两个新的叶节点,并将新对象分配给其中一个。类似地,当从R树中删除对象时,算法会找到包含该对象的叶节点,并将其从树中删除。


4. 查询操作:
R树支持各种查询操作,如范围查询、最近邻查询等。范围查询用于找到落在指定矩形区域内的所有对象,而最近邻查询则返回距离给定点最近的单个对象。这些查询可以通过遍历R树并检查每个叶节点中的对象来实现。


5. 应用场景:
R树广泛应用于各种领域,如地理信息系统、数据库系统、机器人和自动驾驶系统等。它提供了一种有效的方式来索引和查询空间数据,特别是在需要快速响应的空间查询场景中。


R树是一种非常有效的数据结构,用于处理多维空间数据,广泛应用于地理信息系统、空间数据库和搜索引擎等领域的开发和应用。


看一个源码示例:

import java.util.*;  
  
class RTree {  
    class Node {  
        public Rectangle bounds;  
        public List<Node> children;  
        public List<SpatialObject> objects;  
  
        public Node(Rectangle bounds) {  
            this.bounds = bounds;  
            this.children = new ArrayList<>();  
            this.objects = new ArrayList<>();  
        }  
    }  
  
    private Node root;  
  
    public RTree() {  
        root = new Node(new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE));  
    }  
  
    public void insert(SpatialObject obj) {  
        root.insert(obj);  
    }  
  
    public List<SpatialObject> query(Rectangle bounds) {  
        return root.query(bounds);  
    }  
}  
  
class SpatialObject {  
    public int id;  
    public Rectangle bounds;  
  
    public SpatialObject(int id, Rectangle bounds) {  
        this.id = id;  
        this.bounds = bounds;  
    }  
}  
  
class Rectangle {  
    public int x1, y1, x2, y2;  
  
    public Rectangle(int x1, int y1, int x2, int y2) {  
        this.x1 = x1;  
        this.y1 = y1;  
        this.x2 = x2;  
        this.y2 = y2;  
    }  
}

在这个Demo中,我们增加了更多的类和方法来扩展R树的数据结构和功能。RTree类包含一个内部类Node,用于表示R树的节点。每个节点包含一个区域范围(由Rectangle表示)、子节点列表和空间对象列表。SpatialObject类表示空间中的一个对象,它包含一个唯一的ID和对应的矩形区域。Rectangle类保持不变,用于定义矩形的区域范围。


在RTree类中,添加了insert方法来插入新的空间对象,以及query方法来查询落在指定范围内的空间对象。这些方法可以递归地遍历R树,并根据需要执行插入和查询操作。具体的实现细节将取决于R树的构建和查询算法。


✔️什么是B树(B-tree)


1. 定义与结构:
B树(B-tree)是一种自平衡的树形数据结构,用于存储有序数据。它适用于磁盘或其他直接访问辅助设备,能够提高数据的访问效率。B树的特点是所有的叶子节点都在同一层,并且每个叶子节点包含一定数量的关键字。非叶子节点仅存储关键字和子节点指针,不直接存储数据。


2. 节点与关键字:
B树的节点分为内部节点和叶子节点两种类型。内部节点作为中间层级,用于组织和索引数据,而叶子节点存储所有的数据记录。每个节点包含一定数量的关键字,关键字的数量范围在预定义的最小值和最大值之间。内部节点中的关键字用于索引和指引搜索方向,而叶子节点中的关键字与相应的数据记录关联。


3. 插入与删除操作:
B树的插入操作可能会引起树的分裂和合并。当一个内部节点或叶子节点的关键字数量超过最大值时,需要进行分裂操作,将节点分为两个部分,并创建一个新的父节点。相反,当一个节点的关键字数量低于最小值时,可能会发生合并操作。删除操作也可能导致合并操作。为了保证树的平衡性,插入和删除操作需要遵循特定的规则和策略。


4. 查询操作:
B树的查询操作可以通过递归遍历树来实现。从根节点开始,按照关键字的顺序访问内部节点,直到找到相应的叶子节点。在叶子节点中,根据关键字的顺序进行查找,确定所需的数据记录。由于B树保持数据的有序性,查询操作可以在对数时间内完成,提高了查询效率。


5. 应用场景:
B树广泛应用于数据库管理系统、文件系统、搜索引擎等领域。它提供了一种有效的数据索引和查询方法,能够处理大规模数据集,并保持高效的查询性能。通过优化B树的结构和操作,可以进一步改进其在特定应用场景中的性能表现。


B树是一种自平衡的树形数据结构,通过组织关键字和数据记录,提供高效的查询、插入和删除操作。它适用于直接访问辅助设备,如磁盘和固态硬盘等。通过了解B树的结构、节点、操作和应用场景,可以更好地理解和应用这种数据结构在实际应用中的优势和限制。


看一个关于B树的实现简单的Demo:


class BTreeNode {  
    private int degree; // 节点中关键字的最大数量  
    private List<Integer> keys; // 节点中的关键字列表  
    private List<BTreeNode> children; // 子节点列表  
  
    public BTreeNode(int degree) {  
        this.degree = degree;  
        this.keys = new ArrayList<>();  
        this.children = new ArrayList<>();  
    }  
  
    // 插入一个关键字  
    public void insert(int key) {  
        int index = keys.size() - 1;  
        if (keys.isEmpty()) {  
            keys.add(key);  
        } else {  
            while (index >= 0 && key < keys.get(index)) {  
                index--;  
            }  
            keys.add(index, key);  
        }  
        if (keys.size() > degree) {  
            split();  
        }  
    }  
  
    // 删除一个关键字  
    public void delete(int key) {  
        int index = keys.indexOf(key);  
        if (index != -1) {  
            keys.remove(index);  
            if (keys.size() < degree) {  
                merge();  
            }  
        }  
    }  
  
    // 在节点中搜索一个关键字  
    public boolean search(int key) {  
        int index = keys.indexOf(key);  
        return index != -1;  
    }  
  
    // 合并节点,将一个节点的子节点合并到另一个节点中  
    private void merge() {  
        if (children.isEmpty()) {  
            return; // 没有子节点可合并  
        }  
        BTreeNode firstNode = children.get(0); // 第一个子节点  
        BTreeNode secondNode = children.get(1); // 第二个子节点(如果有)  
        if (secondNode != null) { // 有两个子节点需要合并  
            // 将第二个子节点的关键字和子节点合并到第一个子节点中  
            firstNode.keys.addAll(secondNode.keys);  
            firstNode.children.addAll(secondNode.children);  
            // 移除第二个子节点(如果还有其它子节点,也需要相应调整)  
            children.remove(1); // 移除第二个子节点引用  
        }  
        // 将合并后的第一个子节点添加到父节点的子节点列表中(如果需要)  
        addChild(firstNode); // 父节点的合并方法需要实现添加子节点的逻辑  
    }  
  
    // 分裂节点,将一个节点的关键字和子节点分裂成两个节点  
    private void split() {  
        int midIndex = keys.size() / 2; // 分裂点索引(关键字数量的一半)  
        int midKey = keys.get(midIndex); // 分裂点的关键字(分割点)  
        BTreeNode newNode = new BTreeNode(degree); // 新节点(右子树)  
        newNode.keys.addAll(keys.subList(midIndex + 1, keys.size())); // 将右子树的关键字添加到新节点中  
        newNode.children.addAll(children.subList(midIndex + 1, children.size())); // 将右子树的子节点添加到新节点中(如果需要)  
        keys.subList(0, midIndex).clear(); // 清空分割点左边的关键字(左子树)  
        children.subList(0, midIndex).clear(); // 清空分割点左边的子节点(左子树)  
        // 将新节点添加到父节点的子节点列表中(如果需要)  
        addChild(newNode); // 父节点的分裂方法需要实现添加新节点的逻辑  
    }  
}

✔️B树和B+树的区别


B树和B+树都是用于存储和检索数据的自平衡树结构,但它们在数据存储、节点链接和查询效率等方面存在一些重要的差异。


1. 数据存储方式:B树的所有非叶子节点都存储数据,而B+树只有叶子节点存储数据,非叶子节点只存储关键字和子节点指针。这种差异使得B+树的内部节点可以容纳更多的关键字,从而降低树的高度,提高查询效率。


2. 节点链接:B树的所有节点都通过指针相互连接,而B+树的叶子节点通过指针顺序连接在一起,形成一个链表结构。这种连接方式使得B+树在范围查询时更为高效,因为可以通过链表顺序访问所有叶子节点中的数据。


3. 查询效率:由于B+树的节点链接方式和数据存储方式,使得它的查询效率相对更高。在B+树中,只要找到要查找的关键字,就可以直接通过指针访问到所有的相关数据。而在B树中,需要先找到关键字所在的节点,然后再在该节点中查找具体的数据,这需要更多的时间。


看一个图片:


在这里插入图片描述


4. 磁盘读写性能:B+树更适合磁盘或其他直接访问辅助设备的存储和检索操作。由于B+树的内部节点并不存储数据,所以在进行磁盘读写操作时,只需要读取必要的叶子节点即可,这减少了磁盘IO次数,提高了读写性能。


B树和B+树都是非常有效的数据结构,它们的选择取决于具体的应用场景和需求。在需要高效地存储和检索大量数据时,B+树是一个更好的选择。


✔️B树和B+树在数据存储方面的具体差异


在数据存储方面,B树和B+树存在以下具体差异:

1. 非叶子节点存储的数据类型:B树的非叶子节点不仅存储键值,还存储数据。而B+树的非叶子节点仅存储键值,不存储实际数据。所有数据都存储在叶子节点中。


2. 数据查询效率:由于B+树的非叶子节点不存储数据,所有的数据查询必须到达叶子节点才能完成。这使得B+树的数据查询效率相对稳定,不受数据在树中的位置影响。而B树的数据查询效率则与数据在树中的位置有关,在最坏情况下,可能需要查询至树的高层。


3. 内存使用效率:由于B+树的非叶子节点不存储数据,每个节点能存储更多的键值,这有助于减少树的高度,提高查询效率。而B树每个节点存储数据和键值,使得每个节点能存储的键值数量相对较少,树的高度可能更高。


4. 外部存储适应性:B+树更适合外部存储系统,因为它的非叶子节点只存储键值,不存储数据,这使得每个节点能存储的索引数更多,从而减少了磁盘IO次数,提高了查询效率。


综上所述,B树和B+树在数据存储方面的差异主要表现在非叶子节点的数据存储类型、数据查询效率、内存使用效率和外部存储适应性等方面。


看一个Demo:



/**
*    B树和B+树在数据存储方面的差异。这个例子主要通过展示如何在节点中添加数据来解释两者之间的不同
*/

class BTreeNode {  
    private int degree;  
    private List<Integer> keys;  
    private List<BTreeNode> children;  
    private List<Integer> data; // 存储数据  
  
    public BTreeNode(int degree) {  
        this.degree = degree;  
        keys = new ArrayList<>();  
        children = new ArrayList<>();  
        data = new ArrayList<>();  
    }  
  
    // B树节点的插入方法  
    public void insert(int key, int value) {  
        int index = keys.indexOf(key);  
        if (index == -1) {  
            keys.add(key);  
            data.add(value);  
            if (keys.size() > degree) {  
                split();  
            }  
        } else {  
            // 更新数据值或执行其他逻辑,比如移动数据到相邻节点  
        }  
    }  
  
    // B+树节点的插入方法  
    public void insert(int key) {  
        int index = keys.indexOf(key);  
        if (index == -1) {  
            keys.add(key);  
            if (keys.size() > degree) {  
                split();  
            }  
        } else {  
            // 更新键值或执行其他逻辑,B+树中不会出现重复键值的情况  
        }  
    }  
  
    // B树的分裂方法(包括数据的移动)  
    private void split() {  
        // 实现分裂逻辑,包括数据的移动和子节点的创建等操作  
    }  
}

示例中,B树节点BTreeNode包含一个data列表用于存储数据值,而B+树节点也包含一个keys列表用于存储键值。在B树中,插入操作需要考虑键值是否已存在以及如何处理相应的数据值。而在B+树中,插入操作仅关注键值,不存在重复键值的情况。这些差异体现了B树和B+树在数据存储和处理方面的核心差异。


✔️拓展知识仓


✔️R树和B树的区别


R树和B树都是自平衡树,但在数据存储和查询方面存在一些关键差异:

1. 数据存储:B树是为磁盘或其他直接存储辅助设备设计的,而R树则是在高维空间中使用的数据结构,常用于地理信息系统等需要处理多维数据的领域。


2. 节点结构:B树的每个节点可以有多个子节点,适合文件系统索引。而R树则是在高维空间中扩展B树的结构,每个节点也拥有多个子树。


3. 查询效率:B树在数据库中广泛使用,由于其平衡的特性,它提供了高效的查询速度。相比之下,R树主要针对多维度空间的查询优化。


B树和R树在数据存储、节点结构以及查询效率等方面有所不同。选择哪种数据结构取决于具体的应用场景和需求。


✔️ 那在内存消耗上有什么区别?


在内存消耗方面,B树和R树也存在一些差异。

B树需要一次性加载所有元素到内存中,假设有10亿个节点,B+树大概查十几二十次就可以查到叶子节点,那么只需要几十节点加载即可,内存消耗非常少。

而R树由于其结构特点,可能需要更多的内存来存储节点和子树信息。此外,R树在高维空间中扩展B树的结构,每个节点也拥有多个子树,这也会增加内存消耗。

需要注意的是,这里比较的是B树和R树在内存消耗方面的区别,但它们本身的性质决定了其并不在同一个比较环境上,例如B树适用于磁盘或其他直接存储辅助设备,而R树则适用于高维空间数据查询等场景。在实际应用中,还需要考虑其他因素,如查询效率、数据量大小、数据维度等因素来选择合适的数据结构。


在数据库领域中,B树和B+树是最常用的索引结构,而R树则在高维空间数据查询等场景中使用较多。


✔️ R树有哪些优点和缺点


R树是一种自平衡树,适用于高维空间数据的存储和查询。它具有以下优点:

  1. 支持高效的范围查询:R树通过将数据按照地理位置分组,并将每个组的数据分配给一个子树,从而实现了对高维空间数据的范围查询。这使得R树在处理地理信息系统等需要大量范围查询的应用中非常有用。
  2. 适用于高维数据:R树适用于高维空间数据的存储和查询,可以在多个维度上进行数据索引。这使得R树在处理多维数据时具有较好的性能。
  3. 可扩展性好:R树具有良好的可扩展性,可以方便地添加或删除节点,使得它能够适应数据动态变化的情况。

R树也存在一些缺点:

  1. 构建复杂度高:由于R树需要在高维空间中构建平衡树结构,因此构建R树的复杂度较高,需要花费较多的时间和计算资源。
  2. 内存占用较大:由于R树需要存储每个节点的子节点信息,因此相对于其他数据结构,R树的内存占用较大。
  3. 对数据分布敏感:R树对数据的分布比较敏感,如果数据分布不均匀,可能会导致R树的查询性能下降。

总而言之,R树适用于高维空间数据的存储和查询,尤其适用于地理信息系统等需要大量范围查询的应用。但在实际应用中,需要根据具体的需求和场景来选择合适的数据结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/302309.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据库】mysql事务

一、事务的基本概念 1、事务的定义 事务可由一条非常简单的SQL语句组成&#xff0c;也可以由一组复杂的SQL语句组成。。 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性&#xff0c;保证成批的 SQL 语句要么全部执行&…

海外代理IP在游戏中有什么作用?

随着科技的飞速发展&#xff0c;手机和电脑等电子产品已成为互联网连接万物的重要工具&#xff0c;深度融入我们的日常生活&#xff0c;我们借助互联网完成工作、休闲和购物等任务&#xff0c;以求提升生活质量。 不仅如此&#xff0c;网络游戏也是人们心中最爱&#xff0c;它…

2024.1.8每日一题

LeetCode 回旋镖的数量 447. 回旋镖的数量 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定平面上 n 对 互不相同 的点 points &#xff0c;其中 points[i] [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 &#xff0c;其中 i 和 j 之间的距离和 i 和 k 之间的欧式…

Prometheus Blackbox_exporter笔记

一、安装Promtheus 在 Prometheus 官网 Download | Prometheus 获取适用于 Linux 的 Prometheus 安 装包&#xff0c;这里我选择最新的 2.46.0 版本&#xff0c;我是 Linux 系统&#xff0c;选择下载 prometheus-2.46.0.linux-amd64.tar.gz 下载安装包&#xff1a; wget htt…

UI自动化测试神器:RunnerGo

UI自动化测试已经成为现代软件开发过程中不可或缺的一部分。它能够提供诸多优势&#xff0c;包括提高测试效率、减少人力成本、提升软件质量等。同时&#xff0c;可视化工具为UI自动化测试带来了更多便利和灵活性。然而&#xff0c;可视化工具也存在一些潜在的劣势。本文将探讨…

读元宇宙改变一切笔记01_起源

1. 元宇宙是我们下一个生存之地 1.1. 1968年&#xff0c;只有不到10%的美国家庭拥有彩色电视&#xff0c;但当年票房排名第二位的电影《2001&#xff1a;太空漫游》&#xff08;2001: A Space Odyssey&#xff09;设想了这样的未来 1.1.1. 斯坦利库布里克(Stanley Kubrick) …

二 数据查询

1、实验目的 理解SQL成熟设计基本规范&#xff0c;熟练运用SQL语言实现数据基本查询&#xff0c;包括但表查询、分组统计查询和连接查询。 2、实验内容及要求 针对数据库设计各种单表查询SQL语句、分组统计查询语句&#xff1b;设计单个表针对自身的连接查询&#xff0c;设计…

lc 140. 单词拆分 II

回溯算法查询匹配单词 class Solution { public:unordered_map<string, int> word_map;void mapping(vector<string>& wordDict){for(auto &a : wordDict)word_map[a];}vector<string> ret;// s: 原始字符串// tmp: 已查询到的单词// …

【Flutter 开发实战】Dart 基础篇:最基本的语法内容

在深入了解 Dart 这门编程语言之前&#xff0c;我们需要了解一些关于 Dart 的最基本的知识&#xff0c;像是常量、变量、函数等等&#xff0c;这样才能够让我们的开发效率更上一层楼。在本节&#xff0c;我们将探讨一些基础语法&#xff0c;包括入口方法 main、变量、常量以及命…

光伏组件QUV紫外加速老化试验箱

一、产品特点 QUV紫外加速老化试验箱能模拟阳光中 UV340波段光谱的荧光紫外灯&#xff0c;并结合控温、供湿等装置来模拟对材料造成变色、亮度、强度下降&#xff1b;开裂、剥落、粉化、氧化等损害的阳光&#xff0c;以及高温、高湿、凝露、黑暗周期等因素&#xff0c;同时通过…

Linux文件系统与日志分析管理

目录 一、文件系统 1. inode表 2. 查看inode号 3. 文件目录 4. 三种时间戳 5. 删除文件空间不释放 6. 文件恢复extundelete 7. xfs类型备份和恢复 二、日志分析 1. 日志的种类 2. 内核和公共日志 3. 用户日志 3.1 查询当前登录的用户情况 3.2 查询用户登录的历史记…

Linux-添加虚拟内存,不添加硬盘方式操作

在linux中&#xff0c;当物理内存mem不足时&#xff0c;就会使用虚拟内存(swap分区) 例如增加2G虚拟内存&#xff0c;操作如下: 1.查看内存大小 [rootlocalhost ~]# free -m 2.创建要作为swap分区的文件:增加1GB大小的交换分区&#xff0c;则命令写法如下&#xff0c;其中的cou…

免费的开源低代码平台推荐

1.JNPF 最后&#xff0c;推荐一个近期用的不错的低代码。 应用地址&#xff1a;https://www.jnpfsoft.com?csdn 开发语言&#xff1a;Java/.net 这是一个基于 Java Boot/.Net Core 构建的简单、跨平台快速开发框架。前后端封装了上千个常用类&#xff0c;方便扩展&#xf…

Redis分布式锁(二)基于Redis的分布式锁

一、redis锁 1、思路 利用set nx ex获取锁&#xff0c;并设置过期时间&#xff0c;保存线程标识释放锁时先判断线程标识是否与自己一致&#xff0c;一致则删除 2、特性 利用set nx满足互斥性利用set ex保证故障时锁依然能释放&#xff0c;避免死锁&#xff0c;提高安全性利…

普冉32位单片机 PY32C642,M0+内核,1.7 V ~ 5.5 V宽工作电压

PY32C642 单片机采用高性能的 32 位 ARM Cortex-M0内核&#xff0c;宽电压工作范围。嵌入 24Kbytes Flash 和 3 Kbytes SRAM 存储器&#xff0c;最高工作频率 24 MHz。包含多种不同封装类型产品。工作温度范围为-40C ~ 85C&#xff0c;工作电压范围 1.7 V ~ 5.5 V。1 路 12 位A…

影响代理IP稳定性的因素有哪些?

代理IP作为一种网络服务&#xff0c;在生活中扮演着各种各样的角色。它们可以用于保护隐私、突破访问限制、提高网络安全性等。代理IP的稳定性受到多种因素的影响&#xff0c;下面和大家探讨一下影响代理IP稳定性的因素。 1、网络环境&#xff1a;代理IP所处的网络环境对它的稳…

【一】达梦数据库安装和使用-Windows

达梦数据库安装和使用-Windows 简介&#xff1a; 新能源行业关系到国计民生&#xff0c;保障能源安全的意识不容懈怠&#xff0c;近些年各行各业都在推进数字化进程&#xff0c;能源行业在国家3060双碳目标提出之后更是进行的如火如荼&#xff0c;能源互联网方面在数字化的同时…

【设计模式】访问者模式

一起学习设计模式 目录 前言 一、概述 二、结构 三、案例实现 四、优缺点 五、使用场景 六、扩展 总结 前言 【设计模式】访问者模式——行为型模式。 一、概述 定义&#xff1a; 封装一些作用于某种数据结构中的各元素的操作&#xff0c;它可以在不改变这个数据结构…

URL编码揭秘:为什么要进行URL编码?

URL&#xff08;Uniform Resource Locator&#xff0c;统一资源定位符&#xff09;是互联网上资源地址的唯一标识符。在网络请求和数据传输过程中&#xff0c;URL编码起着至关重要的作用。 URL编码解码 | 一个覆盖广泛主题工具的高效在线平台(amd794.com) https://amd794.com…

基于JAVA的中小学教师课程排课系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 角色管理模块2.2 课程档案模块2.3 排课位置模块2.4 排课申请模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 课程表3.2.3 排课位置表3.2.4 排课申请表 四、系统展示五、核心代码5.1 查询课程5.2 新增课…