c/c++手撕B树
-
B-树是一个非二叉树的多路平衡查找树(数据有序),是一颗所有数据都存储在树叶节点上的树,不一定存储具体的数据,也可以是指向包含数据的记录的指针或地址
-
对于阶为M(子节点数量在2和M之间)的B-树具有一下结构特性:
-
树的根节点或者叶子节点,或者子节点数的范围为[2,M]
-
B树每个结点关键字数量为[ceil(2/M)-1,M-1]
-
除根外,所有非树叶节点的子节点数在[ceil(2/M),M]之间,ceil为向上取整函数
-
所有的树叶都在相同的深度上
-
插入操作
-
插入在叶子节点进行
-
向B树中插入数据,根据非叶子节点的关键字找到正确的存储数据的叶子节点。
-
如果节点内的数据小于M-1(M为阶数),就根据排列规则插入;如果节点能够存储的数据已经满了,就进行分裂节点(叶子节点)
分裂节点操作步骤:
-
先看看该叶子节点的关键字数量是否小于M-1(M为阶数)
-
按顺序插入进去,节点的关键字数量如果大于M-1,就将该叶子节点分裂成两个叶子节点,两个叶子节点的数据各占原叶子节点的一半,中间的关键字(数据)作为根节点的关键字,剩下分成两部分的节点作为其(中间关键字形成的根节点)左右节点。当根节点大于M-1的时候,就分裂根节点!
-
如果小于则根据插入的关键字大小按顺序插入。
-
删除操作
-
通过递归找到指定删除的节点
-
删除的关键字在非叶子节点上,就将其左边的指向叶子节点中的最大值跟要删除的关键字互换,就递归进去删除最大值。
-
删除的关键字在叶子节点上
-
叶子节点的关键字个数大于ceil(M/2-1),直接删除
-
叶子节点的关键字个数等于ceil(M/2-1),向父节点借关键字
-
-
递归返回上一层后检查该节点的关键字数,如果小于ceil(M/2-1),就向父节点借关键字,合并该关键字的左右节点,然后不断返回上一层,不断地检查,向父节点借关键字,合并子节点直到返回到根节点。
实现的代码:
我这里使用到了c 的STL的动态数组vector容器和pair对组,大部分还是用c写的,毕竟数据结构用c手撕才有意义,代码中的nullptr对应着c的NULL,splitNode函数为分裂节点函数,merge函数为合并节点函数
-
-
-
using namespace std;
-
-
struct btree{
-
int level; //树的阶数
-
vector<int>keys; //关键字数组
-
vector<btree*>child; //子节点数组
-
int keynum; //节点的关键字数目
-
btree* parent; //子节点的父节点
-
};
-
-
btree* createNode(int level){
-
auto p=new btree;
-
p->level=level;
-
p->keynum=0;
-
p->parent= nullptr;
-
for(int i=0;i<=p->level;i ){
-
p->child.push_back(nullptr);
-
p->keys.push_back(0);
-
}
-
return p;
-
}
-
-
pair<btree*,int> find(btree* root,int key){
-
int i;
-
for(i=root->keynum;i>0;i--){
-
if(key<root->keys[i]){
-
continue;
-
}else if(key>root->keys[i]){
-
break;
-
}else{
-
return make_pair(root,i);
-
}
-
}
-
pair<btree*,int>p=find(root->child[i],key);
-
return p;
-
}
-
-
-
void splitNode(btree* &root,btree* p,int index){
-
if(p!=nullptr){
-
if(p->keynum==p->level){
-
//分裂节点
-
int mid=p->keynum/2 p->keynum%2;
-
btree* newnode= createNode(p->level);
-
newnode->parent=p->parent;
-
for(int j=root->keynum;j>index-1;j--){
-
root->keys[j 1]=root->keys[j];
-
}
-
root->keys[index]=p->keys[mid];
-
root->keynum ;
-
for(int j=mid 1;j<=p->keynum;j ){
-
newnode->keys[j-mid]=p->keys[j];
-
newnode->keynum ;
-
}
-
p->keynum=p->keynum-newnode->keynum-1;
-
int k;
-
for(k=root->level-1;k>index-1;k--){
-
root->child[k 1]=root->child[k];
-
}
-
k ;
-
root->child[k]=newnode;
-
}
-
}
-
if(root->keynum==root->level) {
-
btree *newchild = createNode(root->level);
-
int mid = root->keynum / 2 root->keynum % 2;
-
for (int i = mid 1; i <= root->level; i ) {
-
newchild->keys[i - mid] = root->keys[i];
-
newchild->keynum ;
-
}
-
for (int j = newchild->keynum; j <= newchild->level; j ) {
-
if(root->child[j])
-
root->child[j]->parent=newchild;
-
newchild->child[j - newchild->keynum] = root->child[j];
-
root->child[j] = nullptr;
-
}
-
if (root->parent == nullptr) {
-
btree *newnode = createNode(root->level);
-
newnode->keys[1] = root->keys[mid];
-
newnode->keynum ;
-
root->keynum = root->level - newchild->keynum - 1;
-
newnode->child[0] = root;
-
newnode->child[1] = newchild;
-
root->parent = newnode;
-
newchild->parent = newnode;
-
root = newnode;
-
} else {
-
newchild->parent = root->parent;
-
root->keynum = root->level - newchild->keynum - 1;
-
int a = root->parent->keynum;
-
while (a > 0 && root->keys[mid] < root->parent->keys[a]) {
-
root->parent->keys[a 1] = root->parent->keys[a];
-
root->parent->child[a 1] = root->parent->child[a];
-
a--;
-
}
-
a ;
-
root->parent->keys[a] = root->keys[mid];
-
root->parent->keynum ;
-
root->parent->child[a] = newchild;
-
}
-
}
-
}
-
-
btree* insert(btree* &root,int key){
-
if(0==root->keynum){
-
root->keys[1]=key;
-
root->keynum ;
-
return root;
-
}
-
int index=root->keynum;
-
while (index>0&&key<root->keys[index]){
-
root->keys[index 1]=root->keys[index];
-
index--;
-
}
-
index ;
-
if(root->child[0]!=nullptr){
-
btree* p;
-
if(index==root->keynum){
-
p=root->child[index 1];
-
}else{
-
p=root->child[index-1];
-
}
-
if(root->child[0]->child[0]!=nullptr){
-
p= insert(p,key);
-
}else if(root->child[0]->child[0]==nullptr){
-
int i=p->keynum;
-
while (i>0&&key<p->keys[i]){
-
p->keys[i 1]=p->keys[i];
-
i--;
-
}
-
i ;
-
p->keys[i]=key;
-
p->keynum ;
-
}
-
splitNode(root,p,index);
-
}else{
-
root->keys[index]=key;
-
root->keynum ;
-
splitNode(root, nullptr,-1);
-
}
-
return root;
-
}
-
-
int findmax(btree* root){
-
if(nullptr==root){
-
return 0;
-
}else if(root->child[0]!= nullptr){
-
return findmax(root->child[root->keynum]);
-
}
-
return root->keys[root->keynum];
-
}
-
-
-
void merge(btree* &root,int key,int min,int n){
-
int n1 = root->child[n-1]->keynum;
-
int n2 = root->child[n]->keynum;
-
if (n1 > min) {
-
for (int j = n2; j > 0; j--) {
-
root->child[n]->keys[j 1] = root->child[n]->keys[j];
-
root->child[n]->child[j 1] = root->child[n]->child[j];
-
}
-
root->child[n]->child[1] = root->child[n]->child[0];
-
root->child[n]->keys[1] = root->keys[n];
-
root->keys[n]=root->child[n-1]->keys[n1];
-
root->child[n]->child[0] = root->child[n-1]->child[n1];
-
root->child[n-1]->child[n1] = nullptr;
-
root->child[n-1]->child[0]->parent = root->child[n-1];
-
root->child[n-1]->keynum--;
-
root->child[n-1]->keys[n1] = NULL;
-
root->child[n]->keynum ;
-
} else if (n2 > min) {
-
root->child[n-1]->keys[n1 1]=root->keys[n];
-
root->keys[n]=root->child[n]->keys[1];
-
root->child[n-1]->child[n1 1] = root->child[n]->child[0];
-
root->child[n-1]->child[n1 1]->parent = root->child[n-1];
-
root->child[n-1]->keynum ;
-
for (int j = 1; j < n2; j ) {
-
root->child[n]->keys[j] = root->child[n]->keys[j 1];
-
root->child[n]->child[j - 1] = root->child[n]->child[j];
-
}
-
root->child[n]->child[n2-1]=root->child[n]->child[n2];
-
root->child[n]->keys[n2] = NULL;
-
root->child[n]->child[n2] = nullptr;
-
root->child[n]->keynum--;
-
} else {
-
root->child[n-1]->keys[n1 1]=root->keys[n];
-
root->child[n-1]->keynum ;
-
int n3 = n2 n1 1;
-
for (int j = n1 2; j <= n3; j ) {
-
root->child[n-1]->keys[j] = root->child[n]->keys[j - n1-1];
-
root->child[n-1]->child[j-1]=root->child[n]->child[j];
-
root->child[n-1]->keynum ;
-
}
-
root->child[n]=nullptr;
-
int index = root->keynum;
-
while (index > n && key < root->keys[index]) {
-
root->keys[index-1]=root->keys[index];
-
root->child[index-1]=root->child[index];
-
index--;
-
}
-
root->child[root->keynum]= nullptr;
-
root->keynum--;
-
if(root->parent== nullptr&&root->keynum==0){
-
root->child[0]->parent= nullptr;
-
root=root->child[0];
-
}
-
}
-
}
-
-
void del(btree* &root,int key){
-
if(nullptr==root){
-
return;
-
}else{
-
int i;
-
for(i=root->keynum;i>0;i--){
-
if(key<root->keys[i]){
-
continue;
-
}else if(key>root->keys[i]){
-
del(root->child[i],key);
-
}else{
-
break;
-
}
-
}
-
int min=(root->level/2 root->level%2)-1;
-
if(0==i){
-
if(root->child[i]&&root->child[i 1]){
-
if(root->child[i]->keynum>=min&&root->child[i 1]->keynum>=min){
-
del(root->child[i],key);
-
}
-
}
-
i ;
-
}
-
if(root->child[0]!= nullptr){
-
if(root->keynum>=min){
-
if(root->keys[i]==key){
-
int temp= findmax(root->child[i-1]);
-
root->keys[i]=temp;
-
del(root->child[i-1],temp);
-
merge(root,key,min,i);
-
}else if(key<root->keys[i]){
-
if(root->child[i-1]->keynum<min){
-
merge(root,key,min,i);
-
}
-
}else{
-
if(root->child[i]->keynum<min){
-
merge(root,key,min,i);
-
}
-
}
-
}else{
-
merge(root,key,min,i);
-
}
-
}else{
-
int j;
-
for(j=1;j<root->keynum;j ){
-
if(root->keys[j]==key){
-
break;
-
}
-
}
-
for(int d=j;d<root->keynum;d ){
-
root->keys[d]=root->keys[d 1];
-
}
-
root->keys[root->keynum]=NULL;
-
if(root->keynum>min){
-
root->keynum--;
-
}else{
-
root->keynum--;
-
int index=root->parent->keynum;
-
for(int k=root->keynum;k>0;k--){
-
root->keys[k 1]=root->keys[k];
-
}
-
while (index>0&&key<=root->parent->keys[index]){
-
index--;
-
}
-
if(0==index){
-
root->keys[root->keynum 1]=root->parent->keys[1];
-
}else{
-
root->keys[root->keynum 1]=root->parent->keys[index];
-
}
-
}
-
}
-
}
-
}
-
-
//中序遍历
-
void inorderprint(btree* root){
-
if(nullptr!=root){
-
int i;
-
for(i=0;i<root->keynum;i ){
-
if(root->child[i]!= nullptr){
-
inorderprint(root->child[i]);
-
}
-
cout<<root->keys[i 1]<<" ";
-
}
-
if(root->child[i]!= nullptr)
-
inorderprint(root->child[i]);
-
}
-
}
-
-
-
int main(){
-
btree* root= createNode(4);
-
insert(root,1);
-
insert(root,2);
-
insert(root,3);
-
insert(root,4);
-
insert(root,10);
-
insert(root,15);
-
insert(root,23);
-
insert(root,28);
-
insert(root,30);
-
insert(root,31);
-
insert(root,32);
-
insert(root,33);
-
insert(root,34);
-
insert(root,35);
-
insert(root,36);
-
insert(root,37);
-
insert(root,38);
-
insert(root,39);
-
insert(root,40);
-
insert(root,41);
-
insert(root,42);
-
insert(root,43);
-
insert(root,44);
-
del(root,31);
-
inorderprint(root);
-
system("pause");
-
return 0;
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhggfhjf
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13