B树的实现
来源:互联网 发布:淘宝网的鞋货源哪里找 编辑:程序博客网 时间:2024/06/05 20:49
二叉搜索树我们已经了解了很多种形式了,有AVLTree、红黑树等,不过,这都是在二叉搜索树的基础上加了些东西(平衡因子、颜色),其本质还是二叉搜索树。现在我们遇到一个问题:要是要查找的数据量很大的时候,还用这个,那么树的深度将会很深,那么要怎么解决呢?
要保证数据量不变的情况下,将树的深度降低。这就是B树了,今天我们就来了解一下B树的原理,以及实现过程。
B-树的定义(数据结构书上就是这么写的,不要读作:B减树):它是一种平衡的多路查找树,在文件系统中很有用。
B-树的性质:(假设树为M叉树)
1、若根结点不是叶子结点,那么至少有两棵树
2、每一个非根节点都至少有M/2-1(上取整)个关键字,至多有M-1个关键字,并以升序排序
3、每个非根节点至少有M/2(上取整)个孩子,至多有M个孩子
4、key[i]与key[i+1]之间的孩子的关键字介于key[i]与key[i+1]之间
5、所有的叶子结点都在同一层
#include<iostream>using namespace std;template<class K, size_t M>struct BTreeNode{ //K _keys[M-1]; // 关键字的集合 //BTreeNode<K, M> _pSub[M]; // 孩子的集合 // 多给一个关键字:为简化分裂的逻辑(先将关键字放进去,再分裂) K _keys[M]; // 关键字的集合 BTreeNode<K, M>* _pSub[M + 1]; // 孩子的集合 BTreeNode<K, M>* _pParent; size_t _size; // 有效关键字的个数 BTreeNode() : _size(0) , _pParent(NULL) { for (size_t idx = 0; idx < M + 1; ++idx) _pSub[idx] = NULL; }};template<class K, size_t M>class BTree{ typedef BTreeNode<K, M> Node;public: BTree() : _pRoot(NULL) {} //查找,返回节点以及key在结点中的位置下标 pair<Node*, int> Find(const K& key) { Node* pCur = _pRoot; Node* parent = NULL; while (pCur) { size_t i = 0; while (i < pCur->_size) { if (key < pCur->_keys[i]) break; else if (key>pCur->_keys[i]) i++; else return make_pair(pCur, i); } parent = pCur;//注意! pCur = pCur->_pSub[i]; } return make_pair(parent, -1); } bool Insert(const K& key) { //树空,直接插入 if (NULL == _pRoot) { _pRoot = new Node; _pRoot->_keys[0] = key; _pRoot->_size = 1; return true; } //寻找插入位置 pair<Node*, int> pos = Find(key); if (pos.second >= 0)//要插入的key存在 return false; Node* pCur = pos.first; Node* pSub = NULL;//指关键字右边的孩子,随着关键字的搬移,也要搬移 K k = key;//向上更新的时候不会改变原来key的值 while (true) { _InsertKey(pCur, k, pSub); //看是否满足B-Tree的性质,不满足,则开始分裂 if (pCur->_size < M) return true; //不满足,那么_size只会是M size_t mid = M >> 1; //创建一个新的节点,将mid以后的,都放在新节点中 Node* newNode = new Node; size_t i = mid + 1;//将i ,提出来,增加它的生命周期(for后面还要用) for (; i < M; i++) { newNode->_keys[newNode->_size] = pCur->_keys[i]; newNode->_pSub[newNode->_size] = pCur->_pSub[i]; Node* sub = newNode->_pSub[newNode->_size]; if (sub) sub->_pParent = newNode; ++(newNode->_size); } //处理最右边的一个孩子 newNode->_pSub[newNode->_size] = pCur->_pSub[i]; Node* sub = newNode->_pSub[newNode->_size]; if (sub) sub->_pParent = newNode; pCur->_size = pCur->_size - newNode->_size - 1;//不要忘记pCur的size已经改变了 //将mid放入根结点 if (_pRoot == pCur)//根结点就是pCur { _pRoot = new Node; _pRoot->_keys[0] = pCur->_keys[mid]; _pRoot->_pSub[0] = pCur; _pRoot->_pSub[1] = newNode; //更新双亲 pCur->_pParent = _pRoot; newNode->_pParent = _pRoot; _pRoot->_size = 1; return true; } else { //向上更新 k = pCur->_keys[mid]; pCur = pCur->_pParent; pSub = newNode; } } } //中序遍历 void InOrder() { cout << " InOrder:"; _InOrder(_pRoot); cout << endl; }private: void _InOrder(Node* pRoot) { if (pRoot) { for (int i = 0; i < pRoot->_size; i++) { _InOrder(pRoot->_pSub[i]); cout << pRoot->_keys[i] << " "; } _InOrder(pRoot->_pSub[pRoot->_size]); } } void _InsertKey(Node* pCur, const K& key, Node* pSub) { int end = pCur->_size - 1; while (end >= 0) { //从后往前,如果,要插入的key小于当前的key,那么将这个关键字(和孩子)向后搬移 if (key < pCur->_keys[end]) { pCur->_keys[end + 1] = pCur->_keys[end]; //搬key pCur->_pSub[end + 2] = pCur->_pSub[end + 1]; //搬sub } else break; end--; } pCur->_keys[end + 1] = key; pCur->_pSub[end + 2] = pSub;//不要忘了孩子 if (pSub) pSub->_pParent = pCur; pCur->_size++; }private: Node* _pRoot;};void TestBTree(){ BTree<int, 3> t; t.Insert(10); t.Insert(30); t.Insert(20); t.Insert(40); t.Insert(50); t.Insert(38); t.Insert(35); t.InOrder();}int main(){ TestBTree(); return 0;}
下面是这个插入 数据的分裂过程,可以参考一下
阅读全文
0 0
- B+树的实现
- B+树的实现
- B树的实现
- B树的实现
- b树的实现
- B树的实现
- B树的实现
- B树、B+树的java实现
- B树----B-TREE的实现
- B树和B树的实现 B-Tree
- B树的java实现
- B-树的C++实现
- B树的C实现
- java b+树的实现
- B树数据结构的实现
- B树的C实现
- B树的C实现
- B树的C++实现
- hackerrank>Dashboard>C++>STL> Maps-STL
- java获取执行时间
- mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost'
- LibGdx框架 之 tmx地图文件属性基本操作
- 【一头扎进JMS】(2)----ActiviteMQ点对点消息实现
- B树的实现
- letex使用方法
- Treap 全操作模板 bzoj 3224 普通平衡树
- R语言集成学习
- 简单的本地验证
- LeetCode-70. Climbing Stairs
- C语言作业-3-1奇偶个数
- Kotlin for Android
- Python与Excel之一 xlrd读取excel