【BTree、B-树】B树的C++实现
来源:互联网 发布:手机淘宝怎么进咸鱼 编辑:程序博客网 时间:2024/06/03 21:46
一、B树的概念
B树是平衡的多叉树,一个节点有多于两个(不能小于)结点的平衡多叉树。
由于B树倒着生长所以平衡。
缺点:浪费空间
二、B树满足以下性质:
1、根结点至少有两个孩子。[2,M]个孩子
2、每个非根结点有【(M/2),M】个孩子。
3、每个非根结点有【(M/2-1),M-1】个关键字,并且以升序排序。
4、每个结点孩
5、key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间
6、所有的叶子结点在同一层
三、结点的构造:
由于B树的性质,我们写出了如下每个结点应该包含的内容。
- 包含大小为M-1的kvs数组,但是要方便我们后续的插入分裂操作,所以多开一个结点方便我们分裂 ,即大小为M的kvs数组
- 包含了父节点指针
- 包含结点指针类型的数组,数组中存放的是孩子指针
- 包含size_t参数,代表实际关键字数量
- 最后写上构造函数
四、树的构造:
(1)查找结点:
查找结点返回值是一个pair,如果找到了结点,返回结点cur和此结点的位置,没有找到则返回父节点和-1。
查找的具体过程就是遍历结点构成的数组即可,需要注意的是边界条件,同时在遍历过程中看在树的左边和后面。
(2)插入:
分裂原理:
如果M为3设置数组大小为3(注意不能为2),当结点数为3时候要分裂,左右分裂的时候,先找中位数,中位数右边的结点分一半,中位数左边的结点分一半,中位数占一个,为父亲结点。
需要注意的是:
不能向非叶子结点插入
为了让结点插入传入的是pair K,V
插入方法:
①如果ROOT为空,则构造结点直接插入,需要注意的是调整size
②对树进行查找,调用查找函数,接收返回值。
③由于返回值是一个pair,所以判断返回值的第二个参数,如果存在,则参数为大于等于0,插入不成功返回false,否则进行插入。
④没有找到的时候返回pair的第一个参数是插入节点的父亲结点,构造节点调用insertKV(此处逻辑复杂,单独写出来)进行插入。
⑤判断插入后结点的size值,如果小于M则直接插入成功,反之需要进行分裂。
⑥分离时调用DivideNode函数,
如上两图把分裂的情况全部列举出来,这便是B树实现的难点所在,理解了分裂,便理解了插入。
B+树在没有结点的时候是直接创建两个
五、代码实现:
#include <iostream>using namespace std;template<class K, class V, size_t M>struct BTreeNode{ pair<K, V> _kvs[M]; // 多开一个空间,方便分裂 BTreeNode<K, V, M>* _subs[M+1]; BTreeNode<K, V, M>* _parent; size_t _size; // 关键字的数量 BTreeNode() :_parent(NULL) ,_size(0) { for (size_t i = 0; i < M+1; ++i) { _subs[i] = NULL; } }};template<class K, class V, size_t M>class BTree{ typedef BTreeNode<K, V, M> Node;public: BTree() :_root(NULL) {} pair<Node*, int> Find(const K& key) { Node* parent = NULL; Node* cur = _root; while (cur) { size_t i = 0; while(i < cur->_size) { if (cur->_kvs[i].first > key) // 在[i]的左树 break; else if (cur->_kvs[i].first < key) // 在后面 ++i; else return make_pair(cur, i); } parent = cur; cur = cur->_subs[i]; } return make_pair(parent, -1); } bool Insert(const pair<K, V>& kv) { if (_root == NULL) { _root = new Node; _root->_kvs[0] = kv; _root->_size = 1; return true; } pair<Node*, int> ret = Find(kv.first); if (ret.second >= 0) { return false; } Node* cur = ret.first; pair<K, V> newKV = kv; Node* sub = NULL; // 往cur插入newKV, sub while (1) { InsertKV(cur, newKV, sub); if (cur->_size < M) { return true; } else { // 分裂 Node* newNode = DivideNode(cur); pair<K, V> midKV = cur->_kvs[cur->_size/2]; cur->_size -= (newNode->_size+1); // 1.根节点分裂 if (cur == _root) { _root = new Node; _root->_kvs[0] = midKV; _root->_size = 1; _root->_subs[0] = cur; _root->_subs[1] = newNode; cur->_parent = _root; newNode->_parent = _root; return true; } else { sub = newNode; newKV = midKV; cur = cur->_parent; } } } } //分裂结点 Node* DivideNode(Node* cur) { Node* newNode = new Node; int mid = cur->_size/2; size_t j = 0; size_t i = mid+1; for (; i < cur->_size; ++i) { //此处体现了kvs的作用 newNode->_kvs[j] = cur->_kvs[i]; newNode->_subs[j] = cur->_subs[i]; if(newNode->_subs[j]) newNode->_subs[j]->_parent = newNode; newNode->_size++; j++; } newNode->_subs[j] = cur->_subs[i]; if(newNode->_subs[j]) newNode->_subs[j]->_parent = newNode; return newNode; } //单独写出来,逻辑比较复杂 void InsertKV(Node* cur, const pair<K, V>& kv, Node* sub) { int end = cur->_size-1; while (end >= 0) { if (cur->_kvs[end].first > kv.first) { cur->_kvs[end+1] = cur->_kvs[end]; cur->_subs[end+2] = cur->_subs[end+1]; --end; } else { break; } } cur->_kvs[end+1] = kv; cur->_subs[end+2] = sub; if(sub) sub->_parent = cur; cur->_size++; } //中序遍历 void InOrder() { _InOrder(_root); cout<<endl; } void _InOrder(Node* root) { if (root == NULL) return; Node* cur = root; size_t i = 0; for (; i < cur->_size; ++i) { _InOrder(cur->_subs[i]); cout<<cur->_kvs[i].first<<" "; } _InOrder(cur->_subs[i]); }private: Node* _root;};void TestBTree(){ BTree<int, int, 3> t; int a[] = {53, 75, 139, 49, 145, 36, 101}; for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i) { t.Insert(make_pair(a[i], i)); } t.InOrder();}
六、B树应用:
B和B+树主要用在文件系统以及数据库做索引.比如Mysql;
阅读全文
0 0
- 【BTree、B-树】B树的C++实现
- B-Tree/BTree 的Java实现
- B-Tree/BTree 的Java实现
- B树的C实现
- B树的C实现
- B树的C实现
- C语言-B树(B-树)的完整实现
- BTree,B-Tree,B+Tree,B*Tree的数据结构
- B树的原理与实现(C++)
- [c#]BPlusTreePrototype - B+树的C#实现
- b树的实现(c++)
- B树C语言实现
- B+树C语言实现
- 多路平衡树—BTree(B树)
- B+树的实现
- B+树的实现
- B树的实现
- B树的实现
- iOS 自动化单元测试--XCTest
- 不成熟的想法:装载内核模块的容器
- CentOS 6.8 安装 MySQL 5.1及简单配置
- hibernate多对多demo
- 回文串问题两题
- 【BTree、B-树】B树的C++实现
- JZOJsenior3470.【NOIP2013模拟联考8】最短路(path)
- device_create() class_create()
- dairy
- Springboot多realm集成,无ini文件,无xml配置
- KEIL调用GCC编译STM32
- 阿里云 安装 python 全家桶
- 解惑 spring 嵌套事务
- 2016-9第一题关于最大波动