是一种平衡的多叉树
B树是一颗空树或满足如下的性质:
根节点至少有两个孩子
每个非根节点有[
M/2,M]个孩子
每个非根节点有[M/2-1,M-1]个关键字,并且以升序排列
key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间
所有的叶子节点都在同一层
以下代码实现了B树的查找和插入操作,删除操作暂未实现
插入:先找到插入结点的位置,插入后判断关键字的个数是否小于M(M为阶数),小于返回,不小于进行分裂。
删除:任一关键字K的中序前趋(后继)必是K的左子树(右子树)中最右(左)下的结点中最后(最前)一个关键字。
BTree.h
#pragma once
#include <iostream>
template<class K,int M>
struct BTreeNode
{
K _keys[M];
BTreeNode* _subs[M+1];
BTreeNode* _parents;
size_t _size;
BTreeNode()
: _parents(NULL)
, _size(0)
{
int i = 0;
for (; i < M; ++i){
_keys[i] = 0;
_subs[i] = NULL;
}
}
};
template<class K,int M>
class BTree
{
typedef BTreeNode<K, M> Node, *Node_P;
public:
BTree()
:_root(NULL)
{}
~BTree()
{}
public:
std::pair<Node_P, int> Find(const K& key)
{
if (_root == NULL)
return std::pair<Node_P, int >(NULL,-1);
Node_P cur = _root;
Node_P parent = NULL;
while (cur){
size_t i = 0;
while (i < cur->_size){
if (key == cur->_keys[i]){
return std::pair<Node_P, int >(cur, i);
}
else if (key > cur->_keys[i]){
i++;
}
else
break;
}
parent = cur;
cur = cur->_subs[i];
}
return std::pair<Node_P, int >(parent, -1);
}
bool Insert(const K& key)
{
if (_root == NULL){
_root = new Node;
_root->_keys[0] = key;
_root->_size++;
return true;
}
std::pair<Node_P, int > res = Find(key);
if (res.second != -1)
return false;
K newkey = key;
Node_P cur = res.first;
Node_P sub = NULL;
while (1){
int res_index = _Insert(cur, newkey);
cur->_subs[res_index + 1] = sub;
//满足规则,关键字个数小于M
if (cur->_size < M)
return true;
//不满足,进行分裂
Node_P tmp = new Node;
sub = tmp;
size_t div = (cur->_size - 1) / 2; //中位数
//size_t div = MidNum(cur);//快排的方法求中位数
size_t i = div + 1;
size_t index = 0;
while (i < cur->_size){
tmp->_keys[index] = cur->_keys[i];
tmp->_subs[index] = cur->_subs[i];
cur->_keys[i] = K();
cur->_subs[i] = NULL;
tmp->_size++;
cur->_size--;
index++;
i++;
}
tmp->_subs[index] = cur->_subs[i];
cur->_subs[i] = NULL;
newkey = cur->_keys[div];
cur->_keys[div] = K ();
cur->_size--;
cur = cur->_parents;
if (cur == NULL){
cur = new Node;
cur->_keys[0] = newkey;
cur->_size++;
cur->_subs[1] = sub;
sub->_parents = cur;
cur->_subs[0] = _root;
_root->_parents = cur;
_root = cur;
break;
}
else{
sub->_parents = cur;
}
}
}
//任一关键字K的中序前趋(后继)必是K的左子树(右子树)中最右(左)下的结点中最后(最前)一个关键字。
//bool Remove(K& key);
void InOrder()
{
_InOrder(_root);
std::cout << std::endl;
}
private:
int _Insert(Node_P& cur, K &key)
{
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->_size++;
return end + 1;
}
void _InOrder(Node_P root)
{
if (root == NULL)
return;
int i = 0;
for (; i < root->_size; ++i){
_InOrder(root->_subs[i]);
std::cout << root->_keys[i]<<" ";
}
_InOrder(root->_subs[i]);
}
private:
Node_P _root;
};
void Test1()
{
BTree<int,3> b;
int a[7]={53, 75, 139, 49, 145, 36, 101};
for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
b.Insert(a[i]);
}
b.InOrder();
}
BTree.cpp
#include "BTree.h"
int main()
{
Test1();
return 0;
}
《完》
转载于:https://blog.51cto.com/lingdandan/1828742