您的位置:首页 > 理论基础 > 数据结构算法

数据结构-----------B树

2016-07-22 22:03 435 查看
一、B 树(平衡的多叉树)

  一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树,可以是空树,它的性质为:

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

2、每个非根节点有[⌈M/2⌉,M]个孩子;⌈M/2⌉向上取整

3、每个非根节点有[⌈M/2⌉-1,M-1]个关键字,并且以升序排列

4、key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间‘

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

二、基本操作

(1)查找

(2)中序遍历

(3)插入

三、代码实现:

#pragma once
#include<iostream>
#include<utility>
using namespace std;
template<class K,int M>
struct BTreeNode
{
BTreeNode()
:_parent(NULL)
,_size(0)
{
for(int i=0;i<M+1;i++)
{
_subs[i]=NULL;
}
}
K _keys[M];
BTreeNode<K,M>* _subs[M+1];
BTreeNode<K,M>* _parent;
size_t _size;
};
template<class K,int M>
class BTree
{
public:
typedef BTreeNode<K,M> Node;
BTree()
:_root(NULL)
{}
Node* Find(K key)  //查找key存在位置
{
if(_root==NULL)
{
return NULL;
}
Node* cur=_root;
Node* parent=NULL;
int end=cur->_size-1;
while(cur)
{

parent=cur;
if(key>cur->_keys[end])
{
cur=cur->_subs[end+1];
if(cur)
end=cur->_size-1;

}
else if(key<cur->_keys[end])
{
if(end==0)
{
cur=cur->_subs[end];
if(cur)
end=cur->_size-1;
}
else
end--;
}
else
{
return cur;
}
}
return parent;

}
bool Insert(K key)
{
if(_root==NULL)
{
_root=new Node;
_root->_keys[_root->_size]=key;
_root->_size++;
return true;
}
Node* cur=Find(key);
while(1)
{
int end=cur->_size-1;
for(size_t i=0;i<end+1;i++) //判断该节点是否存在该关键字(判断返回的是parent还是cur)
{
if(cur->_keys[i]==key)
{
return false;
}
}

while(end>=0&&end<cur->_size)  //插入关键字
{
if(cur->_keys[end]>key)
{
cur->_keys[end+1]=cur->_keys[end];

}
else
{
cur->_keys[end+1]=key;
cur->_size++;
break;
}
end--;
if(end==-1)
{
cur->_keys[end+1]=key;
cur->_size++;
break;
}

}
end=cur->_size-1;
Node* parent=cur->_parent;
int div=M/2;
Node* tmp;
if(cur->_size>=M)  //分裂
{
int index=0;
tmp=new Node;
for(int i=div+1;i<cur->_size;i++)  //从M/2处分裂,创建一个新的节点,把M/2后的关键字拷贝到tmp中
{

tmp->_keys[index++]=cur->_keys[i];
tmp->_size++;
}
index=0;
for(int i=div+1;i<cur->_size+1;i++)  //从M/2处分裂,把M/2后的孩子拷贝到tmp中
{
tmp->_subs[index++]=cur->_subs[i];
}

if(parent!=NULL) //分裂的该节点不为根节点
{
int i=parent->_size;
if(i==M-1)   //如果分裂的该节点是parent->_subs[M-1],则不需拷贝前面的parent->_subs[i],直接把创建的tmp节点链在parent->_subs[i]后面
{
parent->_subs[i+1]=tmp;
}
else  //如果分裂的该节点是parent->_subs[i],i<M-1,则需拷贝前面的parent->_subs[i],依次把parent的孩子指针向后移动,空出合适位置,链起tmp
{
while(parent->_subs[i]!=cur)
{
parent->_subs[i+1]=parent->_subs[i];
i--;
}
parent->_subs[i+1]=tmp;
}

tmp->_parent=parent;
}

else   //分裂的该节点为根节点
{
Node* root=new Node;
root->_keys[0]=cur->_keys[div];
root->_subs[0]=cur;
root->_subs[1]=tmp;
cur->_parent=root;
tmp->_parent=root;
_root=root;
_root->_size++;
}

}
else
{
return true;
}
cur->_size=cur->_size-tmp->_size-1;   //把cur->_keys[M/2]插入上层,进行循环
int new_key=cur->_keys[div];
cur=cur->_parent;
key=new_key;
}

}
void InOrder()
{
_InOrder(_root);
}
private:
void _InOrder(Node* root)
{
if(root==NULL)
{
return;
}
int i=0;
for(;i<root->_size;i++)
{
_InOrder(root->_subs[i]);
cout<<root->_keys[i]<<"->";
}
_InOrder(root->_subs[i]);
}

private:
Node* _root;
};
#include "BTree.h"
int main()
{
BTree<int,3> b1;
BTree<int,4> b2;
BTree<int,5> b3;
int a[]={53,75,139,49,145,36,101,36,24,56};
for(int i=0;i<sizeof(a)/sizeof(a[0]);i++)
{
b1.Insert(a[i]);
}
for(int i=0;i<sizeof(a)/sizeof(a[0]);i++)
{
b2.Insert(a[i]);
}
for(int i=0;i<sizeof(a)/sizeof(a[0]);i++)
{
b3.Insert(a[i]);
}

cout<<"三叉:";b1.InOrder();
cout<<endl;
cout<<"四叉:";b2.InOrder();
cout<<endl;
cout<<"五叉:";b3.InOrder();
cout<<endl;
system("pause");
return 0;
}
四、结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: