SQLite B+树实现代码
生活随笔
收集整理的這篇文章主要介紹了
SQLite B+树实现代码
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?
from http://www.sqlite.com.cn/MySqlite/6/373.Html
這個(gè)結(jié)構(gòu)一般用于數(shù)據(jù)庫的索引,綜合效率非常高,像 Berkerly DB , sqlite , mysql 數(shù)據(jù)庫都使用了這個(gè)算法處理索引。
如果想自己做個(gè)小型數(shù)據(jù)庫,可能參考一下這個(gè)算法的實(shí)現(xiàn),可能會(huì)對(duì)你有所幫助。
其中的注釋很詳細(xì),不用再多說了。
/*?btrees.h?*/?/*?
*?平衡多路樹的一種重要方案。?
*?在?1970?年由?R.?Bayer?和?E.?McCreight?發(fā)明。?
*/?
#define?M?1?
/*?B?樹的階,即非根節(jié)點(diǎn)中鍵的最小數(shù)目。?
*?有些人把階定義為非根節(jié)點(diǎn)中子樹的最大數(shù)目。?
*/?
typedef?int?typekey;?
typedef?struct?btnode?{?/*?B-Tree?節(jié)點(diǎn)?*/?
int?d;?/*?節(jié)點(diǎn)中鍵的數(shù)目?*/?
typekey?k[2*M];?/*?鍵?*/?
char?*v[2*M];?/*?值?*/?
struct?btnode?*p[2*M+1];?/*?指向子樹的指針?*/?
}?node,?*btree;?
/*?
*?每個(gè)鍵的左子樹中的所有的鍵都小于這個(gè)鍵,?
*?每個(gè)鍵的右子樹中的所有的鍵都大于等于這個(gè)鍵。?
*?葉子節(jié)點(diǎn)中的每個(gè)鍵都沒有子樹。?
*/?
/*?當(dāng)?M?等于?1?時(shí)也稱為?2-3?樹?
*?+----+----+?
*?|?k0?|?k1?|?
*?+-+----+----+---?
*?|?p0?|?p1?|?p2?|?
*?+----+----+----+?
*/?
extern?int?btree_disp;?/*?查找時(shí)找到的鍵在節(jié)點(diǎn)中的位置?*/?
extern?char?*?InsValue;?/*?與要插的鍵相對(duì)應(yīng)的值?*/?
extern?btree?search(typekey,?btree);?
extern?btree?insert(typekey,btree);?
extern?btree?delete(typekey,btree);?
extern?int?height(btree);?
extern?int?count(btree);?
extern?double?payload(btree);?
extern?btree?deltree(btree);?
/*?end?of?btrees.h?*/?
/*******************************************************/?
?
/*******************************************************/?/*?btrees.c?*/?
#include?
#include?
#include?"btrees.h"?
btree?search(typekey,?btree);?
btree?insert(typekey,btree);?
btree?delete(typekey,btree);?
int?height(btree);?
int?count(btree);?
double?payload(btree);?
btree?deltree(btree);?
static?void?InternalInsert(typekey,?btree);?
static?void?InsInNode(btree,?int);?
static?void?SplitNode(btree,?int);?
static?btree?NewRoot(btree);?
static?void?InternalDelete(typekey,?btree);?
static?void?JoinNode(btree,?int);?
static?void?MoveLeftNode(btree?t,?int);?
static?void?MoveRightNode(btree?t,?int);?
static?void?DelFromNode(btree?t,?int);?
static?btree?FreeRoot(btree);?
static?btree?delall(btree);?
static?void?Error(int,typekey);?
int?btree_disp;?/*?查找時(shí)找到的鍵在節(jié)點(diǎn)中的位置?*/?
char?*?InsValue?=?NULL;?/*?與要插的鍵相對(duì)應(yīng)的值?*/?
static?int?flag;?/*?節(jié)點(diǎn)增減標(biāo)志?*/?
static?int?btree_level?=?0;?/*?多路樹的高度?*/?
static?int?btree_count?=?0;?/*?多路樹的鍵總數(shù)?*/?
static?int?node_sum?=?0;?/*?多路樹的節(jié)點(diǎn)總數(shù)?*/?
static?int?level;?/*?當(dāng)前訪問的節(jié)點(diǎn)所處的高度?*/?
static?btree?NewTree;?/*?在節(jié)點(diǎn)分割的時(shí)候指向新建的節(jié)點(diǎn)?*/?
static?typekey?InsKey;?/*?要插入的鍵?*/?
btree?search(typekey?key,?btree?t)?
{?
int?i,j,m;?
level=btree_level-1;?
while?(level?>=?0){?
for(i=0,?j=t->d-1;?i?t->k[m])?(i=m+1):(j=m));?
if?(key?==?t->k){?
btree_disp?=?i;?
return?t;?
}?
if?(key?>?t->k)?/*?i?==?t->d-1?時(shí)有可能出現(xiàn)?*/?
i++;?
t?=?t->p;?
level--;?
}?
return?NULL;?
}?
btree?insert(typekey?key,?btree?t)?
{?
level=btree_level;?
InternalInsert(key,?t);?
if?(flag?==?1)?/*?根節(jié)點(diǎn)滿之后,它被分割成兩個(gè)半滿節(jié)點(diǎn)?*/?
t=NewRoot(t);?/*?樹的高度增加?*/?
return?t;?
}?
void?InternalInsert(typekey?key,?btree?t)?
{?
int?i,j,m;?
level--;?
if?(level?<?0){?/*?到達(dá)了樹的底部:?指出要做的插入?*/?
NewTree?=?NULL;?/*?這個(gè)鍵沒有對(duì)應(yīng)的子樹?*/?
InsKey?=?key;?/*?導(dǎo)致底層的葉子節(jié)點(diǎn)增加鍵值+空子樹對(duì)?*/?
btree_count++;?
flag?=?1;?/*?指示上層節(jié)點(diǎn)把返回的鍵插入其中?*/?
return;?
}?
for(i=0,?j=t->d-1;?i?t->k[m])?(i=m+1):(j=m));?
if?(key?==?t->k)?{?
Error(1,key);?/*?鍵已經(jīng)在樹中?*/?
flag?=?0;?
return;?
}?
if?(key?>?t->k)?/*?i?==?t->d-1?時(shí)有可能出現(xiàn)?*/?
i++;?
InternalInsert(key,?t->p);?
if?(flag?==?0)?
return;?
/*?有新鍵要插入到當(dāng)前節(jié)點(diǎn)中?*/?
if?(t->d?<?2*M)?{/*?當(dāng)前節(jié)點(diǎn)未滿?*/?
InsInNode(t,?i);?/*?把鍵值+子樹對(duì)插入當(dāng)前節(jié)點(diǎn)中?*/?
flag?=?0;?/*?指示上層節(jié)點(diǎn)沒有需要插入的鍵值+子樹,插入過程結(jié)束?*/?
}?
else?/*?當(dāng)前節(jié)點(diǎn)已滿,則分割這個(gè)頁面并把鍵值+子樹對(duì)插入當(dāng)前節(jié)點(diǎn)中?*/?
SplitNode(t,?i);?/*?繼續(xù)指示上層節(jié)點(diǎn)把返回的鍵值+子樹插入其中?*/?
}?
/*?
*?把一個(gè)鍵和對(duì)應(yīng)的右子樹插入一個(gè)節(jié)點(diǎn)中?
*/?
void?InsInNode(btree?t,?int?d)?
{?
int?i;?
/*?把所有大于要插入的鍵值的鍵和對(duì)應(yīng)的右子樹右移?*/?
for(i?=?t->d;?i?>?d;?i--){?
t->k?=?t->k[i-1];?
t->v?=?t->v[i-1];?
t->p[i+1]?=?t->p;?
}?
/*?插入鍵和右子樹?*/?
t->k?=?InsKey;?
t->p[i+1]?=?NewTree;?
t->v?=?InsValue;?
t->d++;?
}?
/*?
*?前件是要插入一個(gè)鍵和對(duì)應(yīng)的右子樹,并且本節(jié)點(diǎn)已經(jīng)滿?
*?導(dǎo)致分割這個(gè)節(jié)點(diǎn),插入鍵和對(duì)應(yīng)的右子樹,?
*?并向上層返回一個(gè)要插入鍵和對(duì)應(yīng)的右子樹?
*/?
void?SplitNode(btree?t,?int?d)?
{?
int?i,j;?
btree?temp;?
typekey?temp_k;?
char?*temp_v;?
/*?建立新節(jié)點(diǎn)?*/?
temp?=?(btree)malloc(sizeof(node));?
/*?
*?+---+--------+-----+-----+--------+-----+?
*?|?0?|??|?M?|?M+1?|??|2*M-1|?
*?+---+--------+-----+-----+--------+-----+?
*?|<-?M+1?->|<-?M-1?->|?
*/?
if?(d?>?M)?{?/*?要插入當(dāng)前節(jié)點(diǎn)的右半部分?*/?
/*?把從?2*M-1?到?M+1?的?M-1?個(gè)鍵值+子樹對(duì)轉(zhuǎn)移到新節(jié)點(diǎn)中,?
*?并且為要插入的鍵值+子樹空出位置?*/?
for(i=2*M-1,j=M-1;?i>=d;?i--,j--)?{?
temp->k[j]?=?t->k;?
temp->v[j]?=?t->v;?
temp->p[j+1]?=?t->p[i+1];?
}?
for(i=d-1,j=d-M-2;?j>=0;?i--,j--)?{?
temp->k[j]?=?t->k;?
temp->v[j]?=?t->v;?
temp->p[j+1]?=?t->p[i+1];?
}?
/*?把節(jié)點(diǎn)的最右子樹轉(zhuǎn)移成新節(jié)點(diǎn)的最左子樹?*/?
temp->p[0]?=?t->p[M+1];?
/*?在新節(jié)點(diǎn)中插入鍵和右子樹?*/?
temp->k[d-M-1]?=?InsKey;?
temp->p[d-M]?=?NewTree;?
temp->v[d-M-1]?=?InsValue;?
/*?設(shè)置要插入上層節(jié)點(diǎn)的鍵和值?*/?
InsKey?=?t->k[M];?
InsValue?=?t->v[M];?
}?
else?{?/*?d?<=?M?*/?
/*?把從?2*M-1?到?M?的?M?個(gè)鍵值+子樹對(duì)轉(zhuǎn)移到新節(jié)點(diǎn)中?*/?
for(i=2*M-1,j=M-1;?j>=0;?i--,j--)?{?
temp->k[j]?=?t->k;?
temp->v[j]?=?t->v;?
temp->p[j+1]?=?t->p[i+1];?
}?
if?(d?==?M)?/*?要插入當(dāng)前節(jié)點(diǎn)的正中間?*/?
/*?把要插入的子樹作為新節(jié)點(diǎn)的最左子樹?*/?
temp->p[0]?=?NewTree;?
/*?直接把要插入的鍵和值返回給上層節(jié)點(diǎn)?*/?
else?{?/*?(d?/*?把節(jié)點(diǎn)當(dāng)前的最右子樹轉(zhuǎn)移成新節(jié)點(diǎn)的最左子樹?*/?
temp->p[0]?=?t->p[M];?
/*?保存要插入上層節(jié)點(diǎn)的鍵和值?*/?
temp_k?=?t->k[M-1];?
temp_v?=?t->v[M-1];?
/*?把所有大于要插入的鍵值的鍵和對(duì)應(yīng)的右子樹右移?*/?
for(i=M-1;?i>d;?i--)?{?
t->k?=?t->k[i-1];?
t->v?=?t->v[i-1];?
t->p[i+1]?=?t->p;?
}?
/*?在節(jié)點(diǎn)中插入鍵和右子樹?*/?
t->k[d]?=?InsKey;?
t->p[d+1]?=?NewTree;?
t->v[d]?=?InsValue;?
/*?設(shè)置要插入上層節(jié)點(diǎn)的鍵和值?*/?
InsKey?=?temp_k;?
InsValue?=?temp_v;?
}?
}?
t->d?=M;?
temp->d?=?M;?
NewTree?=?temp;?
node_sum++;?
}?
btree?delete(typekey?key,?btree?t)?
{?
level=btree_level;?
InternalDelete(key,?t);?
if?(t->d?==?0)?
/*?根節(jié)點(diǎn)的子節(jié)點(diǎn)合并導(dǎo)致根節(jié)點(diǎn)鍵的數(shù)目隨之減少,?
*?當(dāng)根節(jié)點(diǎn)中沒有鍵的時(shí)候,只有它的最左子樹可能非空?*/?
t=FreeRoot(t);?
return?t;?
}?
void?InternalDelete(typekey?key,?btree?t)?
{?
int?i,j,m;?
btree?l,r;?
int?lvl;?
level--;?
if?(level?<?0)?{?
Error(0,key);?/*?在整個(gè)樹中未找到要?jiǎng)h除的鍵?*/?
flag?=?0;?
return;?
}?
for(i=0,?j=t->d-1;?i?t->k[m])?(i=m+1):(j=m));?
if?(key?==?t->k)?{?/*?找到要?jiǎng)h除的鍵?*/?
if?(t->v?!=?NULL)?
free(t->v);?/*?釋放這個(gè)節(jié)點(diǎn)包含的值?*/?
if?(level?==?0)?{?/*?有子樹為空則這個(gè)鍵位于葉子節(jié)點(diǎn)?*/?
DelFromNode(t,i);?
btree_count--;?
flag?=?1;?
/*?指示上層節(jié)點(diǎn)本子樹的鍵數(shù)量減少?*/?
return;?
}?else?{?/*?這個(gè)鍵位于非葉節(jié)點(diǎn)?*/?
lvl?=?level-1;?
/*?找到前驅(qū)節(jié)點(diǎn)?*/?
r?=?t->p;?
while?(lvl?>?0)?{?
r?=?r->p[r->d];?
lvl--;?
}?
t->k=r->k[r->d-1];?
t->v=r->v[r->d-1];?
r->v[r->d-1]=NULL;?
key?=?r->k[r->d-1];?
}?
}?
else?if?(key?>?t->k)?/*?i?==?t->d-1?時(shí)有可能出現(xiàn)?*/?
i++;?
InternalDelete(key,t->p);?
/*?調(diào)整平衡?*/?
if?(flag?==?0)?
return;?
if?(t->p->d?<?M)?{?
if?(i?==?t->d)?/*?在最右子樹中發(fā)生了刪除?*/?
i--;?/*?調(diào)整最右鍵的左右子樹平衡?*/?
l?=?t->p;?
r?=?t->p[i+1];?
if?(r->d?>?M)?
MoveLeftNode(t,i);?
else?if(l->d?>?M)?
MoveRightNode(t,i);?
else?{?
JoinNode(t,i);?
/*?繼續(xù)指示上層節(jié)點(diǎn)本子樹的鍵數(shù)量減少?*/?
return;?
}?
flag?=?0;?
/*?指示上層節(jié)點(diǎn)本子樹的鍵數(shù)量沒有減少,刪除過程結(jié)束?*/?
}?
}?
/*?
*?合并一個(gè)節(jié)點(diǎn)的某個(gè)鍵對(duì)應(yīng)的兩個(gè)子樹?
*/?
void?JoinNode(btree?t,?int?d)?
{?
btree?l,r;?
int?i,j;?
l?=?t->p[d];?
r?=?t->p[d+1];?
/*?把這個(gè)鍵下移到它的左子樹?*/?
l->k[l->d]?=?t->k[d];?
l->v[l->d]?=?t->v[d];?
/*?把右子樹中的所有鍵值和子樹轉(zhuǎn)移到左子樹?*/?
for?(j=r->d-1,i=l->d+r->d;?j?>=?0?;?j--,i--)?{?
l->k?=?r->k[j];?
l->v?=?r->v[j];?
l->p?=?r->p[j];?
}?
l->p[l->d+r->d+1]?=?r->p[r->d];?
l->d?+=?r->d+1;?
/*?釋放右子樹的節(jié)點(diǎn)?*/?
free(r);?
/*?把這個(gè)鍵右邊的鍵和對(duì)應(yīng)的右子樹左移?*/?
for?(i=d;?i?<?t->d-1;?i++)?{?
t->k?=?t->k[i+1];?
t->v?=?t->v[i+1];?
t->p[i+1]?=?t->p[i+2];?
}?
t->d--;?
node_sum--;?
}?
/*?
*?從一個(gè)鍵的右子樹向左子樹轉(zhuǎn)移一些鍵,使兩個(gè)子樹平衡?
*/?
void?MoveLeftNode(btree?t,?int?d)?
{?
btree?l,r;?
int?m;?/*?應(yīng)轉(zhuǎn)移的鍵的數(shù)目?*/?
int?i,j;?
l?=?t->p[d];?
r?=?t->p[d+1];?
m?=?(r->d?-?l->d)/2;?
/*?把這個(gè)鍵下移到它的左子樹?*/?
l->k[l->d]?=?t->k[d];?
l->v[l->d]?=?t->v[d];?
/*?把右子樹的最左子樹轉(zhuǎn)移成左子樹的最右子樹?
*?從右子樹向左子樹移動(dòng)?m-1?個(gè)鍵+子樹對(duì)?*/?
for?(j=m-2,i=l->d+m-1;?j?>=?0;?j--,i--)?{?
l->k?=?r->k[j];?
l->v?=?r->v[j];?
l->p?=?r->p[j];?
}?
l->p[l->d+m]?=?r->p[m-1];?
/*?把右子樹的最左鍵提升到這個(gè)鍵的位置上?*/?
t->k[d]?=?r->k[m-1];?
t->v[d]?=?r->v[m-1];?
/*?把右子樹中的所有鍵值和子樹左移?m?個(gè)位置?*/?
r->p[0]?=?r->p[m];?
for?(i=0;?id-m;?i++)?{?
r->k?=?r->k[i+m];?
r->v?=?r->v[i+m];?
r->p?=?r->p[i+m];?
}?
r->p[r->d-m]?=?r->p[r->d];?
l->d+=m;?
r->d-=m;?
}?
/*?
*?從一個(gè)鍵的左子樹向右子樹轉(zhuǎn)移一些鍵,使兩個(gè)子樹平衡?
*/?
void?MoveRightNode(btree?t,?int?d)?
{?
btree?l,r;?
int?m;?/*?應(yīng)轉(zhuǎn)移的鍵的數(shù)目?*/?
int?i,j;?
l?=?t->p[d];?
r?=?t->p[d+1];?
m?=?(l->d?-?r->d)/2;?
/*?把右子樹中的所有鍵值和子樹右移?m?個(gè)位置?*/?
r->p[r->d+m]=r->p[r->d];?
for?(i=r->d-1;?i>=0;?i--)?{?
r->k[i+m]?=?r->k;?
r->v[i+m]?=?r->v;?
r->p[i+m]?=?r->p;?
}?
/*?把這個(gè)鍵下移到它的右子樹?*/?
r->k[m-1]?=?t->k[d];?
r->v[m-1]?=?t->v[d];?
/*?把左子樹的最右子樹轉(zhuǎn)移成右子樹的最左子樹?*/?
r->p[m-1]?=?l->p[l->d];?
/*?從左子樹向右子樹移動(dòng)?m-1?個(gè)鍵+子樹對(duì)?*/?
for?(i=l->d-1,j=m-2;?j>=0;?j--,i--)?{?
r->k[j]?=?l->k;?
r->v[j]?=?l->v;?
r->p[j]?=?l->p;?
}?
/*?把左子樹的最右鍵提升到這個(gè)鍵的位置上?*/?
t->k[d]?=?l->k;?
t->v[d]?=?l->v;?
l->d-=m;?
r->d+=m;?
}?
/*?
*?把一個(gè)鍵和對(duì)應(yīng)的右子樹從一個(gè)節(jié)點(diǎn)中刪除?
*/?
void?DelFromNode(btree?t,?int?d)?
{?
int?i;?
/*?把所有大于要?jiǎng)h除的鍵值的鍵左移?*/?
for(i=d;?i?<?t->d-1;?i++)?{?
t->k?=?t->k[i+1];?
t->v?=?t->v[i+1];?
}?
t->d--;?
}?
/*?
*?建立有兩個(gè)子樹和一個(gè)鍵的根節(jié)點(diǎn)?
*/?
btree?NewRoot(btree?t)?
{?
btree?temp;?
temp?=?(btree)malloc(sizeof(node));?
temp->d?=?1;?
temp->p[0]?=?t;?
temp->p[1]?=?NewTree;?
temp->k[0]?=?InsKey;?
temp->v[0]?=?InsValue;?
btree_level++;?
node_sum++;?
return(temp);?
}?
/*?
*?釋放根節(jié)點(diǎn),并返回它的最左子樹?
*/?
btree?FreeRoot(btree?t)?
{?
btree?temp;?
temp?=?t->p[0];?
free(t);?
btree_level--;?
node_sum--;?
return?temp;?
}?
void?Error(int?f,typekey?key)?
{?
if?(f)?
printf("Btrees?error:?Insert?%d!?",key);?
else?
printf("Btrees?error:?delete?%d!?",key);?
}?
int?height(btree?t)?
{?
return?btree_level;?
}?
int?count(btree?t)?
{?
return?btree_count;?
}?
double?payload(btree?t)?
{?
if?(node_sum==0)?
return?1;?
return?(double)btree_count/(node_sum*(2*M));?
}?
btree?deltree?(btree?t)?
{?
level=btree_level;?
btree_level?=?0;?
return?delall(t);?
}?
btree?delall(btree?t)?
{?
int?i;?
level--;?
if?(level?>=?0)?{?
for?(i=0;?i?<?t->d;?i++)?
if?(t->v?!=?NULL)?
free(t->v);?
if?(level?>?0)?
for?(i=0;?i<=?t->d?;?i++)?
t->p=delall(t->p);?
free(t);?
}?
return?NULL;?
}?
/*?end?of?btrees.c?*/?
轉(zhuǎn)載于:https://www.cnblogs.com/jojoke/archive/2007/04/13/712210.html
總結(jié)
以上是生活随笔為你收集整理的SQLite B+树实现代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CG笔记之一——透视投影
- 下一篇: 一个不错的SQL储存过程分页,储存过程+