B树的创建
来源:互联网 发布:霍元甲 歌词 知乎 编辑:程序博客网 时间:2024/06/06 01:31
1.B树的概念
一棵M阶的(M>2) 的平衡二叉树,是一棵平衡的M路平衡搜索树,可以是空树或者满足一下性质:
根节点至少有两个孩子;
原因:因为根节点至少有一个关键字,有两个指针域;每个非根节点至少有M/2-1(上取整)个关键字,至多有M-1个关键字,并且以升序排列;
- 每个非根节点至少有M/2(上取整)个孩子,至多有M个孩子;
- key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间
- 所有的叶子节点都在一层(由节点分裂可推导出);
2.为什么我们要引入B树
数据一般保存在磁盘上,若数据量过大则不能全部加载到内存,为了访问所有的数据,我们可以采用二叉搜索树的索引来保存数据,树的节点保存权值和磁盘的地址,这样查找时可以节约时间;
但是这并没有改善上述的问题,当数据量过大,树的高度则会增高,时间复杂度O(logN)还是太大,为了降低树的高度,减少时间复杂度,我们采用多叉搜索树;
3.B树的构建
首先我们应该清楚B树节点中包含了什么内容,如下所示
节点的分裂原则,如下例所示
再插入节点38和35
4.代码实现
#include<stdio.h>#include<utility>#include<iostream>using namespace std;template<class k,size_t M>struct BTreeNode{ BTreeNode() :_size(0) ,_pParent(NULL) { for(size_t idx=0; idx<M+1; ++idx) _pSub[idx] = NULL; } k _keys[M]; //存储键值的数组 BTreeNode* _pSub[M+1]; //存储孩子指针域的指针 BTreeNode* _pParent; size_t _size; //有效键值的个数};template<class k,size_t M>class BTree{ typedef BTreeNode<k,M> Node;public: BTree() :_pRoot(NULL) {} bool Insert(const k& key) { if(_pRoot == NULL) { _pRoot = new Node; _pRoot->_keys[0] = key; _pRoot->_size = 1; return true; } //查找插入节点的位置 pair<Node*,int> ret = Find(key); if(ret.second > -1) return false; Node* pNode = ret.first; Node* pSub = NULL; k valuek = key; //将key值插入我们已经找到的节点 while(true) { _Insert(pNode,valuek,pSub); if(pNode->_size < M) return true; //需要对节点进行分裂 Node* pNewNode = new Node; size_t mid = M/2; size_t index = 0; size_t idx = 0; //搬移元素和孩子指针到pNewNode for(idx=mid+1; idx<pNode->_size; ++idx) { pNewNode->_keys[index] = pNode->_keys[idx]; pNewNode->_pSub[index] = pNode->_pSub[idx]; if(pNode->_pSub[idx]) { pNode->_pSub[idx]->_pParent = pNewNode->_pSub[index]; pNode->_pSub[idx] = NULL; } pNewNode->_size++; pNode->_size--; index++; } pNewNode->_pSub[index] = pNode->_pSub[idx]; if(pNode->_pSub[idx]) { pNode->_pSub[idx]->_pParent = pNewNode->_pSub[index]; pNode->_pSub[idx] = NULL; } pNode->_size = pNode->_size - pNewNode->_size; //判断该节点是否为根节点 if(pNode->_pParent == NULL) { _pRoot = new Node; _pRoot->_keys[0] = pNode->_keys[mid]; _pRoot->_pSub[0] = pNode; pNode->_pParent = _pRoot; _pRoot->_pSub[1] = pNewNode; pNewNode->_pParent = _pRoot; _pRoot->_size++; return true; } else { valuek = pNode->_keys[mid]; pNode = pNode->_pParent; pSub = pNewNode; } } } pair<Node*,int> Find(const k& key) { Node* pCur = _pRoot; Node* pParent = NULL; while(pCur) { int index = 0; while(index < pCur->_size) { if(pCur->_keys[index] > key) { //pCur = pCur->_pSub[index]; break; } else if(pCur->_keys[index] < key) index++; else return pair<Node*,int>(pCur,index); } //if(key > pCur->_keys[index-1]) pParent = pCur; pCur = pCur->_pSub[index];//当key比数组最后一个key值还大时 } return pair<Node*,int>(pParent,-1); }private: void _Insert(Node*& pNode,const k& key,Node* pSub) { int end = pNode->_size-1; while(end > -1) { if(pNode->_keys[end] > key) { pNode->_keys[end+1] = pNode->_keys[end]; pNode->_pSub[end+2] = pNode->_pSub[end+1]; } else break; end--; } pNode->_keys[end+1] = key; pNode->_pSub[end+2] = pSub; if(pSub) pSub->_pParent = pNode; pNode->_size++; }private: Node* _pRoot;};
测试代码:
#include"BTree.cpp"void funtest(){ BTree<int,3> b; b.Insert(10); b.Insert(30); b.Insert(20); b.Insert(40); b.Insert(50); b.Insert(38); b.Insert(35);}int main(){ funtest(); getchar(); return 0;}
阅读全文
0 0
- B树的创建
- 算法练习六 B树上 B树的创建,添加
- 第18章 B树的创建、搜索和插入
- B树,B-树,B+树,B*树的定义
- B树、B-树、B+树、B*树的区别
- B树、B-树、B+树、B*树的区别
- B树、B-树、B+树、B*树的区别
- B树、B-树、B+树、B*树的区别
- B树创建学生管理系统
- 创建集合A,集合B。求表达式(A-B)U(B-A)的值。
- 第十五周 项目4 B-树的创建、插入、删除操作
- B树索引+B树索引逻辑结构图+B树索引是怎么搜索数据+创建B树索引
- 相亲相爱的B家人(B树,B+树,B-树,B*树)
- B,B-,B+,B*树
- B-、B、B+、B*树
- B-树、B+树、B*树的区别
- B-树、B+树、B*树的区别
- B-树、B+树、B*树的区别
- JPEG原理分析及JPEG解码器调试
- 数据库实验三( 数据更新)
- 神经网络学习笔记(三):三种典型的架构
- 【转载】---- Android视频直播的实现
- JavaScript中this的详解
- B树的创建
- BZOJ 1042:[HAOI2008]硬币购物 容斥原理 背包dp
- 模拟赛 :仙人球 tarjan缩点+倍增
- JavaScript对象--(3)
- 关于报Unknown type name 'class'的问题解决
- 使用python编写数据检索脚本
- 折线分割平面
- ReentrantLock分析
- linux shell find 常用用法总结