算法导论18(B树)
来源:互联网 发布:mac驱动下载 编辑:程序博客网 时间:2024/05/21 12:31
插入
BTreeInsert(node *&root,char k)的工作原理
若root是一个满结点,分配一个空结点tmp,让root成为tmp的孩子,让tmp成为新的root,调用BTreeSplitChild(root,1),调用BTreeInsertNonfull(root,k);否则,直接调用BTreeInsertNonfull(root,k)。
BTreeSplitChild(node *x,int i)的工作原理
//x是一个非满结点,x->c[i]是一个满结点
x->c[i]分裂,x->c[i]的中间结点升至x。
BTreeInsertNonfull(node *x,char k)的工作原理
//x是一个非满结点
(1)x是叶结点:
直接将k插入x
(2)x是内部结点:
若x->c[i]是一个满结点,调用BTreeSplitChild(x,i),递归调用BTreeInsertNonfull(x->c[i],k);否则,直接递归调用BTreeInsertNonfull(x->c[i],k)。
删除
BTreeInsert(node *&root,char k)的工作原理
若root只包含一个关键字,root是内部结点,且root->c[1]和root->c[2]都只包含t-1个关键字,调用BTreeMergeChild(root,1),删除root,让root->c[1]成为新的root,调用BTreeDeleteNonempty(root,k);否则,直接调用BTreeDeleteNonempty(root,k)。
BTreeMergeChild(node *x,int i)的工作原理
//x至少包含t个关键字,x->c[i]和x->c[i+1]都只包含t-1个关键字
把x->key[i]和x->c[i+1]合并进x->c[i],删除x中的x->key[i],删除x->c[i+1]。
BTreeInsertNonempty(node *x,char k)的工作原理
//x至少包含t个关键字
(1)关键字k在结点x中,且x是叶结点:
直接删除x中的k。
(2)关键字k在结点x中,且x是内部结点:
a)x->c[i]至少包含t个关键字:
在x中用k的直接前驱k’代替k,递归调用BTreeInsertNonempty(x->c[i],k’)。
b)x->c[i+1]至少包含t个关键字:
在x中用k的直接后继k’代替k,递归调用BTreeInsertNonempty(x->c[i+1],k’)。
c)x->c[i]和x->c[i+1]都只包含t-1个关键字:
调用BTreeMergeChild(x,i),递归调用BTreeDeleteNonempty(x->c[i],k)。
(3)关键字k不在结点x中:
a)x->c[i]只包含t-1个关键字,且x的相邻兄弟至少包含t个关键字:
x向x的相邻兄弟借一个关键字,递归调用BTreeDeleteNonempty(x->c[i],k)。
b)x->c[i]只包含t-1个关键字,且x的相邻兄弟都只包含t个关键字:
合并x和x的相邻兄弟,递归调用BTreeDeleteNonempty(x->c[i-1],k)(左兄弟)或BTreeDeleteNonempty(x->c[i],k)(右兄弟)
c)x->c[i]至少包含t个关键字:
直接递归调用BTreeDeleteNonempty(x->c[i],k)。
#include<iostream>#include<string>using namespace std;const int t=2;struct node{ int n; char key[2*t]; //key[0]保留,只使用key[1..2*t-1] bool leaf; node *c[2*t+1]; //c[0]保留,只使用c[1..2*t] node(int a,bool b):n(a),leaf(b){}};void BTreeCreate(node *&root){ root=new node(0,true);}//x是一个非满结点,x->c[i]是一个满结点void BTreeSplitChild(node *x,int i){ node *y=x->c[i]; node *z=new node(t-1,y->leaf); for(int j=1;j<=t-1;++j)z->key[j]=y->key[t+j]; if(!y->leaf) { for(int j=1;j<=t;++j)z->c[j]=y->c[t+j]; } y->n=t-1; for(int j=x->n;j>=i;--j)x->key[j+1]=x->key[j]; x->key[i]=y->key[t]; for(int j=x->n+1;j>=i+1;--j)x->c[j+1]=x->c[j]; x->c[i+1]=z; ++x->n;}//x是一个非满结点void BTreeInsertNonfull(node *x,char k){ int i=x->n; if(x->leaf) //x是叶结点 { while(i>=1&&k<x->key[i]) { x->key[i+1]=x->key[i]; --i; } x->key[i+1]=k; ++x->n; } else //x不是叶结点 { while(i>=1&&k<x->key[i])--i; ++i; if(x->c[i]->n==2*t-1) //x->c[i]是一个满结点 { BTreeSplitChild(x,i); if(k>x->key[i])++i; } BTreeInsertNonfull(x->c[i],k); }}void BTreeInsert(node *&root,char k){ if(root->n==2*t-1) //根节点是一个满结点 { node *tmp=new node(0,false); tmp->c[1]=root; root=tmp; BTreeSplitChild(root,1); } BTreeInsertNonfull(root,k);}//x至少包含t个关键字,x->c[i]和x->c[i+1]都只包含t-1个关键字void BTreeMergeChild(node *x,int i){ node *y=x->c[i]; node *z=x->c[i+1]; y->key[y->n+1]=x->key[i]; for(int j=1;j<=t-1;++j)y->key[y->n+1+j]=z->key[j]; if(!z->leaf) { for(int j=1;j<=t;++j)y->c[y->n+1+j]=z->c[j]; } y->n=2*t-1; for(int j=i+1;j<=x->n;++j)x->key[j-1]=x->key[j]; for(int j=i+2;j<=x->n+1;++j)x->c[j-1]=x->c[j]; --x->n; delete z;}//x至少包含t个关键字void BTreeDeleteNonempty(node *x,char k){ int i=1; while(k>x->key[i])++i; if(k==x->key[i]) //关键字k在结点x中 { if(x->leaf) //x是叶结点 { for(int j=i+1;j<=x->n;++j)x->key[j-1]=x->key[j]; --x->n; } else //x是内部结点 { if(x->c[i]->n>=t) //x->c[i]至少包含t个关键字 { //直接前驱 node *p=x->c[i]; while(!p->leaf)p=p->c[p->n+1]; x->key[i]=p->key[p->n]; BTreeDeleteNonempty(x->c[i],p->key[p->n]); } else if(x->c[i+1]->n>=t) //x->c[i+1]至少包含t个关键字 { //直接后继 node *p=x->c[i+1]; while(!p->leaf)p=p->c[1]; x->key[i]=p->key[1]; BTreeDeleteNonempty(x->c[i+1],p->key[1]); } else //x->c[i]和x->c[i+1]都只包含t-1个关键字 { BTreeMergeChild(x,i); BTreeDeleteNonempty(x->c[i],k); } } } else //关键字k不在结点x中 { if(x->c[i]->n==t-1) //x->c[i]只包含t-1个关键字 { if(i-1>=1&&x->c[i-1]->n>=t) //相邻左兄弟至少包含t个关键字 { //x中的关键字降至x->c[i] for(int j=x->c[i]->n;j>=1;--j)x->c[i]->key[j+1]=x->c[i]->key[j]; x->c[i]->key[1]=x->key[i-1]; //x->c[i-1]中的关键字升至x x->key[i-1]=x->c[i-1]->key[x->c[i-1]->n]; if(!x->c[i-1]->leaf) { for(int j=x->c[i]->n+1;j>=1;++j)x->c[i]->c[j+1]=x->c[i]->c[j]; x->c[i]->c[1]=x->c[i-1]->c[x->c[i-1]->n+1]; } ++x->c[i]->n; --x->c[i-1]->n; BTreeDeleteNonempty(x->c[i],k); } else if(i+1<=x->n+1&&x->c[i+1]->n>=t) //相邻右兄弟至少包含t个关键字 { //x中的关键字降至x->c[i] x->c[i]->key[x->c[i]->n+1]=x->key[i]; //x->c[i+1]中的关键字升至x x->key[i]=x->c[i+1]->key[1]; for(int j=2;j<=x->c[i+1]->n;++j)x->c[i+1]->key[j-1]=x->c[i+1]->key[j]; if(!x->c[i+1]->leaf) { x->c[i]->c[x->c[i]->n+2]=x->c[i+1]->c[1]; for(int j=2;j<=x->c[i+1]->n+1;++j)x->c[i+1]->c[j-1]=x->c[i+1]->c[j]; } ++x->c[i]->n; --x->c[i+1]->n; BTreeDeleteNonempty(x->c[i],k); } else //相邻左右兄弟都只包含t-1个关键字 { if(i-1>=1) //相邻左兄弟 { BTreeMergeChild(x,i-1); BTreeDeleteNonempty(x->c[i-1],k); } else //相邻右兄弟 { BTreeMergeChild(x,i); BTreeDeleteNonempty(x->c[i],k); } } } else BTreeDeleteNonempty(x->c[i],k); //x->c[i]至少包含t个关键字 }}void BTreeDelete(node *&root,char k){ if(root->n==1&&!root->leaf&&root->c[1]->n==t-1&&root->c[2]->n==t-1) //case 2c或case 3b { BTreeMergeChild(root,1); node *tmp=root; root=root->c[1]; delete tmp; } BTreeDeleteNonempty(root,k);}// KQ// / | \ // BF M TW// / | \ / \ / | \// A CDE H L NP RS V XYZint main(){ node *root; BTreeCreate(root); string s="FSQKCLHTVWMRNPABXYDZE"; for(int i=0;i<s.size();++i)BTreeInsert(root,s[i]); for(int i=0;i<s.size();++i)BTreeDelete(root,s[i]); return 0;}
从B树、B+树、B*树谈到R 树:
http://blog.csdn.net/v_july_v/article/details/6530142
- 算法导论18(B树)
- 算法导论读书笔记(18)B树
- 【算法导论】B树
- 算法导论B树
- 算法导论 B树
- 算法导论-B树
- 算法导论 第18章 B树
- 算法导论-第18章-B树
- 算法导论 第18章 B 树
- 算法导论笔记:18B树
- 《算法导论》第18章 B树
- 算法导论 ch18 B树
- 【算法导论】B树讲解
- 算法导论—B树
- 算法导论之B树
- 算法导论代码 第18章 B树
- 算法导论习题解-第18章B树
- 《算法导论》第18章 B树 个人笔记
- 杭电acm第1003题Max Sum ( 动态规划)
- Codeforces Round 469 C 24 Game
- jquerymobile的helloworld
- HOOK钩子技术5 SSDT Inline Hook
- LeetCode 160 :Intersection of Two Linked Lists
- 算法导论18(B树)
- POJ1698 Alice's Chance(最大匹配)
- java+oracle+web(第七天) tomcat介绍 (四)实现https://www.igo.com 直接访问我的主页
- js 生成随机数方法
- 常用算法之排序算法四【归并排序】
- 机器学习实战 朴素贝叶斯
- 二叉平衡树
- sums
- 使用viewport的元数据、CSS和Javascript来为不同分辨率的屏幕设置合适的页面