一种适合外查找的树,它是一种平衡的多叉树,称为B树。
一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树,可以是空树或者满足一下性质:
根节点至少有两个孩子
每个非根节点有[M/2,M]个孩子
每个非根节点有[M/2-1,M-1]个关键字,并且以升序排列
key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间
所有的叶子节点都在同一层
注:使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。按照翻译,B 通常认为是Balance的简称。这个数据结构一般用于数据库的索引,综合效率较高。
B-tree有以下特性:
1、关键字集合分布在整棵树中;
2、任何一个关键字出现且只出现在一个结点中;
3、搜索有可能在非叶子节点结束;
4、其搜索性能等价于在关键字全集内做一次二分查找;
5、自动层次控制;
鉴于B-tree具有良好的定位特性,其常被用于对检索时间要求苛刻的场合,例如:
1、B-tree索引是数据库中存取和查找文件(称为记录或键值)的一种方法。
2、硬盘中的结点也是B-tree结构的。与内存相比,硬盘必须花成倍的时间来存取一个数据元素,这是因为硬盘的机械部件读写数据的速度远远赶不上纯电子媒体的内存。与一个结点两个分支的二元树相比,B-tree利用多个分支(称为子树)的结点,减少获取记录时所经历的结点数,从而达到节省存取时间的目的。
#pragma once
#include<iostream>
using namespace std;
template<class K,int M>
struct BTreeNode
{
K _keys[M];
BTreeNode<K, M>* _subs[M + 1];
BTreeNode<K, M>* _parent;
size_t _size;
BTreeNode()
:_parent(NULL)
, _size(0)
{
for (int i = 0; i < M; ++i)
{
_keys[i] = K();
_subs[i] = NULL;
}
_subs[M] = NULL;
}
};//K
template<class K,class V,int M>
struct BTreeNodeKV
{
pair<K, V> _kvs[M];
BTreeNodeKV<K, V, M>* _subs[M + 1];
BTreeNodeKV<K, V, M>* _parent;
size_t _size;
};
template<class K,int M>
class BTree
{
typedef BTreeNode<K, M> Node;
public:
BTree()
:_root(NULL)
{}
pair<Node*, int> Find(K& key)
{
if (_root == NULL)
return pair<Node*, int>(NULL, -1);
Node* cur=_root;
Node* parent = NULL;
while (cur)
{
int size = cur->_size;
int i;
for (i = 0; i < size;)
{
if (cur->_keys[i] == key)
return pair<Node*, int>(cur, i);
else if (cur->_keys[i] < key)
{
++i;
}
else
break;
}
parent = cur;
cur = cur->_subs[i];
}
return pair<Node*, int>(parent, -1);
}
void _Insert(Node* cur,K& key, Node* sub)
{
int end = cur->_size - 1;
while (end >= 0)
{
if (cur->_keys[end] > key)
{
cur->_keys[end + 1] = cur->_keys[end];
cur->_subs[end + 2] = cur->_subs[end+1];
--end;
}
else
break;
}
cur->_keys[end + 1] = key;
cur->_subs[end + 2] = sub;
++cur->_size;
if (sub)
sub->_parent=cur;
}
bool Insert(K& key)
{
if (_root == NULL)
{
_root = new Node;
_root->_keys[0] = key;
_root->_size = 1;
return true;
}
else
{
pair<Node*,int> ret = Find(key);
if (ret.second != -1)
return false;
else
{
Node* cur = ret.first;
K newkey = key;
Node* insert_sub = NULL;//第一次插入时insert_sub为NULL
while (1)
{
_Insert(cur, newkey, insert_sub);
if (cur->_size<M)
break;
//分裂
int div = M / 2;
Node* sub = new Node;
int index = 0;
int i = div+1;
while (i < M)
{
sub->_keys[index] = cur->_keys[i];
cur->_keys[i] = K();//还原为K类型的默认值
sub->_subs[index] = cur->_subs[i];
cur->_subs[i] = NULL;
++index;
++i;
++sub->_size;
}
sub->_subs[index] = cur->_subs[i];
cur->_subs[i - 1] = NULL;
cur->_size -= (index+1);//减去右边和key的大小
if (cur->_parent == NULL)
{
_root = new Node;
_root->_keys[0] = cur->_keys[div];
cur->_keys[div] = K();
_root->_subs[0] = cur;
cur->_parent = _root;
_root->_subs[1] = sub;
sub->_parent=_root;
_root->_size = 1;
return true;
}
else
{
insert_sub = sub;
newkey = cur->_keys[div];
cur = cur->_parent;
}
}
return true;
}
}
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
protected:
void _InOrder(Node* root)
{
if (root == NULL)
return;
int i = 0;
for (i = 0; i < root->_size; ++i)
{
_InOrder(root->_subs[i]);
cout << root->_keys[i] << " ";
}
_InOrder(root->_subs[i]);
}
protected:
Node* _root;
};
void Test1()
{
//int arr[] = { 20, 30, 10 };
/*BTree<int, 3> b;
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
{
b.Insert(arr[i]);
}*/
int arr[] = { 53, 75, 139, 49, 145, 36, 101 };
BTree<int, 3> b;
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
{
b.Insert(arr[i]);
}
b.InOrder();
}
#include"BTree.h"
int main()
{
Test1();
system("pause");
return 0;
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。