B树相关操作
来源:互联网 发布:dcs 化工仿真软件 编辑:程序博客网 时间:2024/06/07 07:27
花了一个下午把书上的B树操作看明白了,又花了一天把代码憋出来…主要是操作比较复杂,需要注意的细节太多…至于删除操作,书上已经详细说明了过程…累啊
有一个不确定的地方是,不清楚如果重复数据有或者比较多的情况会怎么样
输入样例21F S Q K C L H T V W M R N P A B X Y D Z E 2M T
#include<stdio.h>#include<stdlib.h>#define t 2 typedef struct Bnode{ int n; int leaf; char key[t*2-1]; struct Bnode *c[2*t];}Bnode;typedef struct Btree{ Bnode *root;}Btree;int Bcreate(Btree *T){ T->root=(Bnode *)malloc(sizeof(Bnode)); T->root->n=0; T->root->leaf=1; return 0;}int Bsplitchild(Bnode *x,int i){ Bnode *y,*z; y=x->c[i]; z=(Bnode *)malloc(sizeof(Bnode)); z->leaf=y->leaf; z->n=t-1; for (int j=0;j<t-1;j++) z->key[j]=y->key[t+j]; if (!z->leaf)/*尽量不要操作没有初始化的指针,养成良好的习惯还是很重要滴*/ for (int j=0;j<t;j++) z->c[j]=y->c[j+t]; for (int j=x->n-1;j>=i;j--) x->key[j+1]=x->key[j]; x->key[i]=y->key[t-1]; for (int j=x->n;j>i;j--) x->c[j+1]=x->c[j]; x->c[i+1]=z; x->n++; y->n=t-1; return 0;}int Binsert_nonfull(Bnode *x,char k){ if (x->leaf) { int i; for (i=x->n-1;i>=0 && k<=x->key[i];i--) x->key[i+1]=x->key[i]; i++; x->key[i]=k; x->n++; return 0; } int i; for (i=x->n-1;i>=0 && k<=x->key[i];i--); i++; if (x->c[i]->n==t*2-1) { Bsplitchild(x,i); if (k>x->key[i])/*这里不要忘了*/ i++; } Binsert_nonfull(x->c[i],k); return 0;}int Binsert(Btree *T,char k){ Bnode *root=T->root; if (root->n==t*2-1) { Bnode *s; s=(Bnode *)malloc(sizeof(Bnode)); s->n=0; s->leaf=0; s->c[0]=root; T->root=s; Bsplitchild(s,0); } Binsert_nonfull(T->root,k); return 0;}Bnode *Bsearch(Bnode *x,char k,int *i){ int j; int n=x->n; for (j=n-1;j>=0 && k<=x->key[j];j--); j++; if (/*j>=0 && */j<n && k==x->key[j]) { *i=j; return x; } if (x->leaf) { *i=-1; return NULL; } return Bsearch(x->c[j],k,i);}char successor(Bnode *x,int i)/*求内部节点的后继*/{ Bnode *tmp; for (tmp=x->c[i+1];!tmp->leaf;tmp=tmp->c[0]); return tmp->key[0];}char predecessor(Bnode *x,int i)/*求内部节点的前驱*/{ Bnode *tmp; for (tmp=x->c[i];!tmp->leaf;tmp=tmp->c[tmp->n]); return tmp->key[tmp->n-1];}int Bmerge(Btree *T,Bnode *x,int i)/*合并x.key[i]的左右两个孩子*/{ Bnode *y=x->c[i]; Bnode *z=x->c[i+1]; y->key[y->n]=x->key[i]; int j; for (j=0;j<t-1;j++) y->key[t+j]=z->key[j]; for (j=0;j<t;j++) y->c[t+j]=z->c[j]; y->n=t*2-1; free(z); for (j=i;j<x->n-1;j++) x->key[j]=x->key[j+1]; for (j=i+1;j<x->n;j++) x->c[j]=x->c[j+1]; x->n--; if (x->n==0)/*一定是内部节点*/ { free(x); T->root=y; } return 0;}int Bdelete(Btree *T,Bnode *x,char k)/*疑似有bug,当有重复元素时不知道会不会出错*/{ int i; for (i=x->n-1;i>=0 && k<=x->key[i];i--); i++; if (x->leaf)/*情况1*/ { int j; for (j=i;j<x->n-1;j++) x->key[j]=x->key[j+1]; x->n--; return 0; } if (i<x->n && x->key[i]==k) if (x->c[i]->n>=t)/*情况2a*/ { char k1=predecessor(x,i); x->key[i]=k1; Bdelete(T,x->c[i],k1);/*如果有重复的元素,也不会出错*/ } else if (x->c[i+1]->n>=t)/*情况2b*/ { char k1=successor(x,i); x->key[i]=k1; Bdelete(T,x->c[i+1],k1); } else/*情况2c*/ { Bnode *y=x->c[i]; Bmerge(T,x,i);/*会删除空的非内部空节点*/ Bdelete(T,y,k); } else if (x->c[i]->n>=t)/*情况3,但是可以直接递归*/ Bdelete(T,x->c[i],k); else if (i>0 && x->c[i-1]->n>=t)/*情况3a左*/ { Bnode *y=x->c[i]; Bnode *z=x->c[i-1]; int j; for (j=y->n-1;j>=0;j--) y->key[j+1]=y->key[j]; for (j=y->n;j>=0;j--) y->c[j+1]=y->c[j]; y->key[0]=x->key[i-1];/*细节啊,害我调试这么久*/ y->c[0]=z->c[z->n]; y->n++; x->key[i-1]=z->key[z->n-1];/*这里也是!*/ z->n--; Bdelete(T,y,k); } else if (i<x->n && x->c[i+1]->n>=t)/*情况3a右,边界检查别忘了,虽然这里没有出错*/ { Bnode *y=x->c[i]; Bnode *z=x->c[i+1]; y->key[y->n]=x->key[i]; y->c[y->n+1]=z->c[0]; y->n++; x->key[i]=z->key[0]; int j; for (j=0;j<z->n-1;j++) z->key[j]=z->key[j+1]; for (j=0;j<z->n;j++) z->c[j]=z->c[j+1]; z->n--; Bdelete(T,y,k); } else/*情况3b*/ { Bnode *y=x->c[i]; Bmerge(T,x,i); Bdelete(T,y,k); } return 0;}int print(Bnode *x){ int i; int n=x->n; printf("("); for (i=0;i<n-1;i++) printf("%c ",x->key[i]); if (n) printf("%c",x->key[i]); printf(")"); if (x->leaf) return 0; for (i=0;i<=n;i++) print(x->c[i]); return 0;}int main(void){ Btree T; Bcreate(&T); int n; scanf("%d\n",&n); for (int i=0;i<n;i++) { char k; scanf("%c ",&k); Binsert(&T,k); } print(T.root); printf("\n"); scanf("%d\n",&n); for (int i=0;i<n;i++) { char k; int j; scanf("%c ",&k); if (Bsearch(T.root,k,&j)) { printf("%c deleted!:",k); Bdelete(&T,T.root,k); print(T.root); printf("\n"); } else printf("%c:not exist!\n",k); } printf("\n"); return 0;}
0 0
- B树相关操作
- B树相关操作纯代码(除删除操作)
- B树相关汇总
- B-tree的构造及相关操作
- B-树和B+的相关知识点
- B-树的操作
- B树基本操作
- B树操作详解
- 【数据结构与算法】B tree 即相关操作 深入解读
- 二叉树相关操作
- 树的相关操作
- 二叉树相关操作
- 树相关的操作
- 树相关操作
- 二叉树相关操作
- 树的相关操作
- 二叉树相关操作
- 二叉树 相关操作
- 富文本原价 现在的价格
- LUA学习(二) 类型、表达式等基础要点
- [Introduction]About Python
- 人生感悟
- linux ssh
- B树相关操作
- Tle格式
- java重载-方法重载中的准确性原则
- C#中限制访问器可访问性
- ATL-连接点和接口方法的使用
- struts2 验证框架validation.xml不起作用的原因
- 形篇
- OpenCV学习笔记(五)—— OpenCV for Android剔除OpenCV Manager依赖
- /dev/fb0入门练习(linux FrameBuffer)