数据结构:神奇的B树实现解析(有图有代码有真相!!!)

一、B树引入

二叉搜索树、平衡二叉树、红黑树都是动态查找树,典型的二叉搜索树结构,查找的时间复杂度和树的高度相关O(log2N)。


1)数据杂乱无章-------线性查找--O(n)

2)数据有序-------二分查找 ---O(log 2 n)  最差退化成单支树-----线性结构

3)二叉搜索树、AVL树、红黑树 --------O(log2 n)

数据一般保存在磁盘上,若数据量过大不能全部加载到内存,为了访问所有数据,使用如下搜索树结构保存数据:树的结点中保存权值和磁盘的地址


那如何加速对数据的访问速度呢?

提高I/O的时间

降低树的高度--平衡多叉树


二、B树定义


1970年,R.Bayer和E.mccreight提出了一种适合外查找的树,它是一种平衡的多叉树,称为B树。
(有些地方写的是B-树,注意不要误读成"B减树")
一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树,可以是空树或者满足一下性质:
1. 根节点至少有两个孩子
2. 每个非根节点至少有M/2(上取整)个孩子,至多有M个孩子
3. 每个非根节点至少有M/2-1(上取整)个关键字,至多有M-1个关键字,并且以升序排列

4. key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间


一次插入的过程:53, 75, 139, 49, 145, 36, 101










#pragma once
#include <iostream>
#include <stdlib.h>using namespace std;template<class K, int M>
struct BTreeNode
{typedef BTreeNode<K, M> Node;K _keys[M];//多给一个位置是为了先插入方便分裂Node* _sub[M+1];Node* _parent;size_t _size;//记录关键字的个数BTreeNode():_parent(NULL),_size(0){for(size_t i = 0; i < M; i++){_keys[i] = K();_sub[i] = 0;}_sub[M] = 0;}
};template<class K, int M>
class BTree
{typedef BTreeNode<K, M> Node;
public:BTree():_pRoot(NULL){}void Inorder(){_Inorder(_pRoot);}~BTree(){_Destroy(_pRoot);}bool Insert(const K& key){if(NULL == _pRoot){_pRoot = new Node();_pRoot->_keys[0] = key;_pRoot->_size++;return true;}pair<Node*, size_t>	temp = _Find(key);if(temp.second != -1){return false;}Node* cur = temp.first;Node* sub = NULL;K newKey = key;while(1){_InsertKey(cur, newKey, sub);if(cur->_size < M){return true;}while(cur->_size >= M){size_t mid = cur->_size / 2;Node* NewNode = new Node;for(size_t i = mid+1; i < cur->_size; i++){int j = 0; //新节点的下标NewNode->_keys[j] = cur->_keys[i];NewNode->_size++;cur->_keys[i] = K();//复制之后,对应的原位置key置为初始值。j++;}int j = 0;for(size_t i = mid+1; i < cur->_size+1; i++){NewNode->_sub[j] = cur->_sub[i];if(NewNode->_sub[j])NewNode->_sub[j]->_parent = NewNode;j++;cur->_sub[i] = NULL;}if(cur == _pRoot){Node* temp = new Node();temp->_keys[0] = cur->_keys[mid];cur->_keys[mid] = K();cur->_size = mid;temp->_size++;temp->_sub[0] = cur;cur->_parent = temp;temp->_sub[1] = NewNode;NewNode->_parent = temp;_pRoot = temp;return true;}newKey = cur->_keys[mid];cur->_keys[mid] = K();cur->_size = mid;sub = NewNode;}cur = cur->_parent;}}protected:pair<Node*, size_t> _Find(const K& key){Node* cur = _pRoot;Node* parent = NULL;while(cur){size_t i = 0;while(i < cur->_size){if(cur->_keys[i] < key)i++;else if(cur->_keys[i] > key)break;elsereturn pair<Node*, size_t>(cur, i);}parent = cur;cur = cur->_sub[i];}return pair<Node*, size_t>(parent, -1);}void _InsertKey(Node* cur,const K& Key,Node* sub){int i = cur->_size-1;while(i >= 0){if(cur->_keys[i] > Key){//移动关键字位置cur->_keys[i+1] = cur->_keys[i];//移动子树的位置cur->_sub[i+2] = cur->_sub[i+1];i--;}elsebreak;}cur->_keys[i+1] = Key;cur->_sub[i+2] = sub;if(sub)sub->_parent = cur;cur->_size++;}void _Inorder(Node* _pRoot){if(NULL == _pRoot)return;size_t i = 0;for(; i < _pRoot->_size; i++){_Inorder(_pRoot->_sub[i]);cout<<_pRoot->_keys[i]<<" ";}_Inorder(_pRoot->_sub[i]);}void _Destroy(Node* _pRoot){if(NULL == _pRoot)return;size_t i = 0;for(; i < _pRoot->_size; i++){_Destroy(_pRoot->_sub[i]);delete _pRoot->_sub[i];}_Destroy(_pRoot->_sub[i]);delete _pRoot->_sub[i];}private:Node* _pRoot;
};void test()
{BTree<int, 3> bt;int array[] = {53, 75, 139, 49, 145, 36, 101};for(int i = 0; i < sizeof(array)/sizeof(array[0]); i++){bt.Insert(array[i]);}bt.Inorder();
}





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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux:dup/dup2 文件描述符重定向函数(有图有代码有真相!!!)

一、dup/dup2 有时我们希望把标准输入重定向到一个文件&#xff0c;或者把标准输出重定向到一个网络连接。系统调用dup和dup2能够复制文件描述符。dup返回新的文件文件描述符&#xff08;没有用的文件描述符最小的编号&#xff09;。 dup2可以让用户指定返回的文件描述符的值…

Linux:I/O多路转接之select(有图有代码有真相!!!)

一、select引入 一次 I/O 分为两个部分&#xff1a;1&#xff09;等待数据就绪 2&#xff09;进行数据转移 1、select 原理&#xff1a; select的原理就是减少等待数据就绪的比重&#xff0c;巧妙的利用等待队列机制让用户进程适当在没有资源可读/写时睡眠&#xff0c;有资…

Linux: I/O多路转接之poll(有图有代码有真相!!!)

一、poll()函数解析 不同与select使⽤用三个位图来表⽰示三个fdset的⽅方式&#xff0c;poll使⽤用⼀一个 pollfd的指针实现。pollfd结构包含了要监视的event和发⽣生的event&#xff0c; 不再使⽤用select“参数-值”传递的⽅方式。同时&#xff0c;pollfd并没有最⼤大数量限…

kalilinux装到u盘上的弊端_付费下载的歌曲,竟然无法在汽车上播放!原因在这里...

『使用某音乐播放器下载了周杰伦的110首歌曲&#xff0c;其中106首是kgm格式&#xff0c;4首mp3格式&#xff0c;装到U盘后&#xff0c;在其它设备播放只有4首mp3格式的可以播放&#xff0c;其它的均无法播放&#xff0c;请问该如何处理&#xff1f;』网友留言截图这是一位网友…

iconsvg image怎么变为path_昆凌是怎么收服天王周杰伦的?这几招太高明了

周杰伦和昆凌又出来撒狗粮了&#xff01;就在前两天(6月2日)&#xff0c;在参加郎朗的婚礼时&#xff0c;#周杰伦搂昆凌看烟花#的消息悄悄上了热搜。视频中&#xff0c;两人并肩站立&#xff0c;一起欣赏着窗外的美景。周杰伦时不时在昆凌的耳边私语几句&#xff0c;看起来很是…

ewebeditor未授权:功能被禁用请先配置授权_SteamPY新功能——外区账号礼物自动领取...

自从PY平台增加了外区代购后发现许多玩家在购买礼物时常会发生收到礼物后准备点击入库时弹出地区不可用的提示这个问题在Steam外区账号一直频繁发生究其因在于Steam账号登录时的IP问题遇到该问题切勿拒收礼物&#xff01;通过Steam客户端清理登录授权注销退出后再次使用账号对应…

Linux: shell 中命令代换 $() 和 ``(有图有代码有真相!!!)

一、命令代换&#xff08;命令替换&#xff09; 由 或 $() 括起来的也是一条命令&#xff0c;shell先执行该命令&#xff0c;再将结果立刻代换到当前命令行中。 简单例子&#xff1a; DATEdate echo $DATE DATE$(date) echo $DATE 执行结果&#xff1a; 二、优缺点&#x…

精雕道路怎么遍弧形_【养护技术】道路“创可贴”——沥青冷补料 六大优势助力道路养护...

点击上面蓝字关注我们微信号&#xff1a;xzgsgl随着城市精细化管理目标不断提高&#xff0c;市政道路养护修补的要求也越来越高。不但对修补的外观、质量有了更高的标准&#xff0c;对修复时限也提出了一定要求&#xff0c;这就要求我们的养护单位快速、优质地完成道路修补任务…

单耳蓝牙耳机怎么连接_蓝牙耳机怎么挑选?推荐性价比高的蓝牙耳机

随着手机逐渐取消了耳机孔&#xff0c;越来越多的人们开始使用上了蓝牙耳机。在当今这个飞速发展的时代&#xff0c;蓝牙耳机无疑成为了新时代的宠儿。无论是上班族还是当代大学生等年轻化群体&#xff0c;耳机的第一选择都是蓝牙耳机。但是面对市面上如此多的蓝牙耳机&#xf…

Linux: shell命令 eval (有图有代码有真相!!!)

一、eval 命令定义 shell中的eval命令将会首先扫描命令行进行所有的替换&#xff0c;然后再执行命令。该命令使用于那些一次扫描无法实现其功能的变量。 该命令对变量进行两次扫描。这些需要进行两次扫描的变量有时候被称为复杂变量。不过这些变量本身并不复杂。eval 命令也可…

qlabel可以选中吗_惊现凡尔赛式排版!原来微信公众号排版样式还可以“变装”?...

各位小伙伴们&#xff0c;要集中注意力了&#xff01;接下来就是考验你们观察力的时候啦&#xff01;快跟着小妹儿看一下&#xff0c;一个样式到底能有多少种玩法&#xff1f;文中使用工具为公众号编辑器-小蚂蚁编辑器。1、添加/删除背景编辑器里的内容样式是可以增加或者删除背…

LInux:shell 彩色进度条实现(有图有代码有真相!!!)

一、进度条原理&#xff08;以前的博客详细讲述过&#xff09;&#xff1a;http://blog.csdn.net/sharp_up/article/details/55506555 二、颜色设置 // 字体颜范围(前景颜色):30~39 30:黑 31:红 32:绿 33:黄 34:蓝色 35:紫色 36:深绿 37:白色 // 字背景颜色范围(背景颜…

Linux: 系统配置 crond 和 crontab(有图有代码有真相!!!)

1、相关概述 linux下工作调度的种类有&#xff1a;at , cron 一种是例行性的&#xff0c;就是每隔一定的周期来办某事。 一种是突发性的&#xff0c;就是做完这一次没有以后。 crontab这个命令所设置的工作将会一直循环进行下去&#xff0c;循环的时间可以是分钟、小时、…

LInux:shell 命令:字符串截取

1、cut命令截取 使用说明 cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。 如果不指定 File 参数&#xff0c;cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。 主要参数 -b &#xff1a;以字节为单位进行分割。这些字节位置将忽…

smart700iev3 程序下载设置_分享一款Aira2下载工具

Qdown&#xff0c;一款新的Aria2下载器&#xff0c;Aria2是一个命令行的下载器&#xff0c;非常强大&#xff0c;本软件套壳了Aria2&#xff0c;并且制作了界面版本&#xff0c;使用体验不错。Qdown是一款基于Aria2的Windows文件下载器&#xff0c;几乎支持现阶段所有的下载协议…

引用js_js值和引用

值和引用在许多编程语言中&#xff0c;赋值和参数传递可以通过值复制或者引用复制来完成&#xff0c;这取决于我们使用什么语法。例如&#xff0c;在 C 中如果要向函数传递一个数字并在函数中更改它的值&#xff0c;就可以这样来声明参 数 int& myNum&#xff0c;即如果传递…

]数据结构:单链表之判断两个链表是否相交及求交点(带环、不带环)

1、判断两个链表是否相交&#xff0c;若相交&#xff0c;求交点。&#xff08;假设链表不带环&#xff09; 两个指针同时指向两个链表&#xff0c;分别依次往后遍历链表到最后一个节点&#xff0c;如指针的值相同&#xff08;即节点地址相同&#xff09;&#xff0c;反之没有交…

某月某日前包括当天吗_10月26日,你真的理解了导数的定义吗?(答思考题送猫王小音箱)...

点击并关注上方“鸡汤斋”&#xff0c;与斋主一起成长特别说明&#xff1a;公众号的“一天一题”都是从历年期中、期末&#xff0c;以及各个高等学校或者国家统一的考研试题中抽取的题目进行的详细讲解。如果您每天在固定的时间(无聊时、吃饭时、睡觉前、早上起床前、“吃鸡”前…

人脸识别进水_万维|人脸识别闸机怎么选?

如今人脸识别在安防行业的逐渐普及&#xff0c;现在已经有越来越多的场景都已应用人脸识别闸机&#xff0c;像办公大厦啊&#xff0c;景区门口&#xff0c;社区门口等&#xff0c;什么都不用带&#xff0c;只要刷个脸就行&#xff0c;方便快捷又省事。那么&#xff0c;你又对人…

基于udp的网络群聊系统

一、系统简介 这是一个基于udp协议的网络群聊系统&#xff0c;为什么选择udp协议呢&#xff1f;这就需要了解TCP协议与udp协议。 1&#xff09;TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09; 是面向连接的协议&#xff0c;也就是说&…