B-树 构建

经常不写博客感觉有些知识都有些模糊,闹了许多笑话。现在开始将自己之前接触到的学习过的,还有正准备学习研究的记录下来。方便自己回看,也便于交流。

今天看到了一种新的搜索结构B-树。之前刚开始接触二叉树时感觉挺简单的,以为树也差不多。今天才发现在插入时挺复杂的。

  B-树——平衡多叉树

    一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树。满足以下性质

  1.根节点至少有两个孩子

  2..每个非根节点有 M/2~M 个孩子

  3.每个非根节点有 M/2-1~M-1.的关键字

  4.key【i】和key【i+1】之间的孩子节点的值介于key【i】 key怕【i+1】之间

  5.所有的叶子节点都在同一层

ps:以上来源资料

《B-树 构建》

    关键字比孩子的个数永远少一个,如下图。且可以将多叉树在每个节点处抽象为关键字个二叉树,如下图关键字为  40  50  ,可看做两个共用一个孩子的二叉树,40 的右孩子与 50 的左孩子共用。这样可帮助理解结构。

   节点

         构建B-树,先分析节点的组成。每个节点都包含一个关键字数组、一个指向孩子上的指针数组,一个指向下一节点的指针组成,为了方便后续的功能实现,再添加一个指向父亲节点的指针。代码如下:

template <class K,class V, size_t M = 3>
struct BTreeNode
{
BTreeNode(const pair<K, V>& kv = pair<K, V>())
{
_parent = NULL;
_size = 0;
for (size_t i = 0; i < M + 1; ++i)
{
_sub[i] = NULL;
}
}
pair<K, V> _kvs[M]; //关键字最多为M-1 ,此处设为M,方便插入,以防越界
BTreeNode<K, V>* _sub[M + 1];//孩子数比关键字大一个
BTreeNode<K, V>* _parent;
size_t _size;
};

      B-树在一个_root的根节点开始满足上面的性质进行的操作。

template <class K, class V, size_t M = 3>
class BTree
{
typedef BTreeNode<K, V> Node;
public:
BTree()
:_root(NULL)
{}
//各种功能实现
protected:
Node* _root;
};

《B-树 构建》

功能

  1.查找Find

pair<Node*, int> Find(const K &key)
{
Node* cur = _root;
Node* parent = NULL;
while (cur)
{
cur->_parent = parent;
size_t i = 0;
for (; i < cur->_size; )
{
if (cur->_kvs[i].first > key)
{
break;
}
else if (cur->_kvs[i].first == key)
{
return make_pair(cur, i);
}
else
{
++i;
}
}
parent = cur;
cur = cur->_sub[i];
}
return make_pair(parent, -1);
}

        2.插入 Insert()

bool Insert(const pair<K, V>&kv)
{

if (_root == NULL)
{
_root = new Node;
_root->_kvs[0] = kv;
_root->_size++;
return true;
}
else
{
pair<Node*, int> ret = Find(kv.first);

if (ret.second != -1)
{
return false;
}
else
{
Node* cur = ret.first;
pair<K, V> newKV = kv;
Node* sub = NULL;
while (1)
{
_InsertKV(cur, newKV, sub);

if (cur->_size < M)
return true;

size_t mid = M / 2;
Node* tmp = new Node;
size_t j = 0;
size_t i = mid + 1;
for (; i < cur->_size; ++i)
{
tmp->_kvs[j] = cur->_kvs[i];
cur->_kvs[i] = pair<K, V>();
tmp->_sub[j] = cur->_sub[i];
if (cur->_sub[i])
cur->_sub[i]->_parent = tmp;
tmp->_size++;
++j;
}

tmp->_sub[j] = cur->_sub[i];
if (cur->_sub[i])
cur->_sub[i]->_parent = tmp;
cur->_size = cur->_size – tmp->_size-1;
if (cur->_parent == NULL)
{
_root = new Node;
_root->_kvs[0] = cur->_kvs[mid];
cur->_kvs[mid] = pair<K, V>();
_root->_size = 1;

_root->_sub[0] = cur;
_root->_sub[1] = tmp;
cur->_parent = _root;
return true;
}

else
{
newKV = cur->_kvs[mid];
sub = tmp;
cur->_kvs[mid] = pair<K, V>();
cur = cur->_parent;

}

}
}

}
}


void _InsertKV(Node* &cur, pair<K, V> &newKV, Node* &sub)
{

for (size_t i = 0; i < cur->_size; ++i)
{
if (newKV.first < cur->_kvs[i].first)
{
for (size_t j = cur->_size; j > i; –j)
{
cur->_kvs[j] = cur->_kvs[j – 1];
cur->_sub[j + 1] = cur->_sub[j];
}
cur->_kvs[i] = newKV;
cur->_sub[i + 1] = sub;
if (sub)
{
sub->_parent = cur;
}
cur->_size++;
return;
}
}
cur->_kvs[cur->_size] = newKV;
cur->_sub[cur->_size + 1] = sub;
if (sub)
{
sub->_parent = cur;
}
cur->_size++;
}

       3.排序 InOrder()

根据B-树的特性,可以利用中序遍历

void InOrder()
{
if (_root == NULL)
return;
_InOrder(_root);
cout << endl;
}

void _InOrder(Node* cur)
{
if (cur == NULL)
return;
size_t i = 0;
for (; i < cur->_size; ++i)
{
_InOrder(cur->_sub[i]);
cout << cur->_kvs[i].first<<” “;
}
_InOrder(cur->_sub[i]);
}


  

    原文作者:B树
    原文地址: https://blog.csdn.net/Dream_JW/article/details/56498680
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞