B树
来源:互联网 发布:淘宝童装批发怎么宣传 编辑:程序博客网 时间:2024/05/26 22:59
#ifndef _TREE_H
#define _TREE_H
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "assert.h"
typedef struct Btree Btree;
typedef struct Cell Cell;
typedef struct Cursor Cursor;
typedef struct Pool Pool;
typedef unsigned int u16;
typedef unsigned char u8;
struct Cell{
char aPayLoad[8];
Pool* leftChild;//左孩子
u16 iNext;//下一个Cell
//key和data
};
struct PoolHead{
Pool* rightChild;//右孩子
u16 firstFree;//第一个空闲块
u16 firstCell;//第一个Cell
};
struct PoolArray{
Pool* k[500];
u8 tag[500];
u8 n;
};
#define MAX_LENGTH 1024
struct Pool{
union{
PoolHead h;
char aDisk[1024+2];
}u;
Pool* pParent;
Cell* apCell[1024/8];//访问点
u16 nCell;
u16 nFree;
u8 isOverfull;
u8 isInit;
u8 idxShift;//如果apCell[]中的索引发生了变化
u8 idxParent;
};
struct Cursor{//指向一个记录
Btree* pBt;
Pool* pPool;
u16 idx;
};
struct Btree{
Pool* root;
int nPool;
PoolArray Number;
};
struct FreeBlk {
u16 iSize; /* 在这个块中自由空间的字节数目?*/
u16 iNext; /* 下一个自由块的.u.aDisk[]的索引 */
};
void CreateBtree(Btree** ppBt,size_t nPool);//创建一个Btree
void DestroyBtree(Btree* pBt);//释放一个Btree
void zeroPool(Pool* pPool);
void initPool(Pool* pPool,Pool* pParent);
void mallocPool(Btree* pBt,Pool**ppPool);
void freePool(Btree* pBt,Pool* pPool);
int mallocCell(Pool* pPool,int sz);
void fillInCell(Cell* pCell,const void* pKey,int nKey,const void* pData,int nData);
void refragmentpool(Pool* pPool);
void initCursor(Btree* pBt,Cursor* pCur);
void movetoroot(Cursor* pCur);
void movetochild(Cursor* pCur);
int moveto(Cursor* pCur,const void* pKey,int nKey);
void relinkCell(Pool*pPool);
void insertCell(Pool* pPool,Cell* pCell,int i,int sz);
void reparent( Pool* pChild, Pool *pNewParent,int idx);
void reparentChild(Btree *pBt, Pool *pPool);
void copyPool(Pool *pTo, Pool *pFrom);
void balance(Btree *pBt, Pool *pPool);
void dropCell(Btree *pBt, Pool *pPool, int idx, int sz);
void freeSpace(Btree *pBt, Pool *pPool, int start, int size);
int BtreeInsert(Cursor *pCur,const void *pKey,int nKey,const void *pData,int nData);
void Test(Pool* pPool,int high);
void BtreeDell(Cursor* pCur,Btree* pBt,const void * pKey,int nKey);
#endif
#include "tree.h"
void CreateBtree(Btree** ppBt,size_t nPool){
(*ppBt)=(Btree*)malloc(sizeof(Btree));
(*ppBt)->root=(Pool*)malloc(sizeof(Pool));
zeroPool((*ppBt)->root);
initPool((*ppBt)->root,0);//父亲页
(*ppBt)->nPool=nPool>10?nPool:nPool;
for(size_t i=0;i<nPool;i++){
(*ppBt)->Number.k[i]=(Pool*)malloc(sizeof(Pool));
(*ppBt)->Number.tag[i]=0;
zeroPool((*ppBt)->Number.k[i]);
}
(*ppBt)->Number.n=nPool;
}
void DestroyBtree(Btree* pBt){
for(int i=0;i<pBt->nPool;i++){
//printf("%d/n",i);
free(pBt->Number.k[i]);
}
free(pBt->root);
free(pBt);
}
void zeroPool(Pool* pPool){
int hdr_sz=sizeof(PoolHead);
FreeBlk* pFree;
memset(pPool,0,1024);
pPool->u.h.rightChild=0;
pPool->u.h.firstCell=0;
pPool->u.h.firstFree=hdr_sz;
pFree=(FreeBlk*)&(pPool->u.aDisk[hdr_sz]);
pFree->iNext=0;
pFree->iSize=1024-hdr_sz;
pPool->isOverfull=0;
pPool->isInit=0;
pPool->nCell=0;
pPool->nFree=1024-hdr_sz;
pPool->pParent=0;
}
void initPool(Pool* pPool,Pool* pParent){
if(pPool->pParent) return ;
if(pParent){
pPool->pParent=pParent;
}
if(pPool->isInit)return ;
pPool->isInit=1;
pPool->nCell=0;
u16 freespace=1024-sizeof(PoolHead);
u16 idx=pPool->u.h.firstCell;
while(idx!=0){//
Cell* pCell=(Cell*)pPool->u.aDisk[idx];
freespace-=sizeof(Cell);
pPool->apCell[pPool->nCell++]=pCell;
idx=pCell->iNext;
}
pPool->nFree=0;
idx=pPool->u.h.firstFree;
while(idx!=0){
FreeBlk* pFBlk=(FreeBlk*)&pPool->u.aDisk[idx];
pPool->nFree+=pFBlk->iSize;
idx=pFBlk->iNext;
}
}
void mallocPool(Btree* pBt,Pool** ppPool){
for(int i=0;i<pBt->nPool;i++){
if(!pBt->Number.tag[i]){
(*ppPool)=pBt->Number.k[i];
pBt->Number.tag[i]=1;
}else{
continue;
}
}
(pBt)->Number.k[pBt->nPool]=(Pool*)malloc(sizeof(Pool));
(pBt)->Number.tag[pBt->nPool]=0;
pBt->nPool++;
zeroPool((pBt)->Number.k[pBt->nPool-1]);
(*ppPool)=(pBt)->Number.k[pBt->nPool-1];
//assert(pBt->nPool<50);
}
void freePool(Btree* pBt,Pool* pPool){
for(int i=0;i<pBt->nPool;i++){
if(pBt->Number.k[i]==pPool){
pBt->Number.tag[i]=0;
return ;
}
}
}
int mallocCell(Pool* pPool,int sz){
FreeBlk* pFree;
u16* pIdx=&pPool->u.h.firstFree;
u16 start=0;
u16 iSize;
//printf("/n%d/n",pPool->nFree);
//assert(pPool->nFree>sz);
if(pPool->nFree<sz)
return -1;
pFree=(FreeBlk*)&pPool->u.aDisk[*pIdx];
while((iSize=pFree->iSize)<sz){
if(pFree->iNext==0){
refragmentpool(pPool);
pIdx=&pPool->u.h.firstFree;
}else{
pIdx=&pFree->iNext;
}
pFree=(FreeBlk*)&pPool->apCell[*pIdx];
}
//assert(pFree->iSize>=sz);
if(iSize==sz){
start=*pIdx;
*pIdx=pFree->iNext;
}else{
start=*pIdx;
FreeBlk* pNew=(FreeBlk*)&pPool->u.aDisk[start+sz];
pNew->iNext=pFree->iNext;
pNew->iSize=iSize-sz;
*pIdx=(start+sz);
}
pPool->nFree-=sz;
return start;
}
void refragmentpool(Pool* pPool){
//assert(1);
char aux[1024];
u16 paux=0;
paux=sizeof(PoolHead);
memcpy(aux,pPool,paux);
for(u16 i=0;i<pPool->nCell;i++){
Cell* pCell=pPool->apCell[i];
memcpy(aux+paux,pCell,sizeof(Cell));
pPool->apCell[i]=(Cell*)&pPool->u.aDisk[paux];
paux+=sizeof(Cell);
}
memcpy(pPool,aux,paux);
pPool->u.h.firstCell=sizeof(PoolHead);
if(pPool->nCell>0){
pPool->apCell[pPool->nCell-1]->iNext=0;
}
FreeBlk* pFree=(FreeBlk*)&pPool->u.aDisk[paux];
pFree->iSize=1024-paux;
pFree->iNext=0;
pPool->u.h.firstCell=paux;
memset(&pFree[i],0,1024-paux-sizeof(FreeBlk));
}
void fillInCell(Cell* pCell,const void* pKey,int nKey,const void* pData,int nData){
pCell->iNext=0;
pCell->leftChild=0;
memcpy(pCell->aPayLoad,pKey,nKey);
memcpy(pCell->aPayLoad+nKey,pData,nData);
}
//cursor的初始化
void initCursor(Btree* pBt,Cursor* pCur){
pCur->idx=0;
pCur->pBt=pBt;
pCur->pPool=0;
}
void movetoroot(Cursor* pCur){
pCur->pPool=pCur->pBt->root;
pCur->idx=0;
}
void movetochild(Cursor* pCur){
if(pCur->idx>=pCur->pPool->nCell){
pCur->pPool=pCur->pPool->u.h.rightChild;
pCur->idx=0;
}else{
pCur->pPool=pCur->pPool->apCell[pCur->idx]->leftChild;
}
}
int moveto(Cursor* pCur,const void* pKey,int nKey){
movetoroot(pCur);
int c=-1;
for(;;){
Pool* pPool=pCur->pPool;
int low=0;
int high=pPool->nCell-1;
while(low<=high){
pCur->idx=(low+high)/2;
c=memcmp(pPool->apCell[pCur->idx],pKey,nKey);
if(c==0)return 0;
if(c<0)low=pCur->idx+1;
if(c>0) high=pCur->idx-1;
}
//printf("/n%d/n",c);
//assert(c<0);
if(low>=pPool->nCell){
pPool=pPool->u.h.rightChild;
}else{
pPool=pPool->apCell[low]->leftChild;
}
if(pPool==0){
// pCur->idx=low;
return c;
}
pCur->idx=low;
movetochild(pCur);
}
}
typedef unsigned int uptr;
#define Addr(X) ((uptr)X)
void relinkCell(Pool* pPool){
u16 idx;
u16* pIdx=&pPool->u.h.firstCell;
for(int i=0;i<pPool->nCell;i++){
idx=Addr(pPool->apCell[i])-Addr(pPool);
*pIdx=idx;
pIdx=&pPool->apCell[i]->iNext;
}
}
void insertCell(Pool* pPool,Cell* pCell,int i,int sz){
int idx=mallocCell(pPool,sz);
//assert(idx>0);
for(int j=pPool->nCell;j>i;j--){
pPool->apCell[j]=pPool->apCell[j-1];
}
pPool->nCell++;
if(idx<0){
pPool->isOverfull=1;
pPool->apCell[i]=pCell;
}else{
//??????????????assert(sz!=16);
memcpy(&pPool->u.aDisk[idx],pCell,sz);
pPool->apCell[i]=(Cell*)&pPool->u.aDisk[idx];
//assert(pPool->apCell[i]!=0);
}
pPool->idxShift=1;
}
void reparent( Pool* pChild, Pool *pNewParent,int idx){
Pool *pThis;
pThis = pChild;
if( pThis && pThis->isInit ){
if( pThis->pParent!=pNewParent ){
pThis->pParent = pNewParent;
}
pThis->idxParent = idx;//他在父亲的apCell[]中的位置
}
}
void reparentChild(Btree *pBt, Pool *pPool){
int i;
for(i=0; i<pPool->nCell; i++){
reparent(pPool->apCell[i]->leftChild, pPool, i);
}
reparent( pPool->u.h.rightChild, pPool, i);
pPool->idxShift = 0;
}
void copyPool(Pool *pTo, Pool *pFrom){
uptr from, to;//uptr
int i;
memcpy(pTo->u.aDisk, pFrom->u.aDisk, 1024);
pTo->pParent = 0;
pTo->isInit = 1;
pTo->nCell = pFrom->nCell;
pTo->nFree = pFrom->nFree;
pTo->isOverfull = pFrom->isOverfull;
to = Addr(pTo);
from = Addr(pFrom);
//调整pTo->apCell[]中的指针,
for(i=0; i<pTo->nCell; i++){
uptr x = Addr(pFrom->apCell[i]);
if( x>from && x<from+1024 ){
*((uptr*)&pTo->apCell[i]) =to+( x - from);
}else{//那些溢出的页码
pTo->apCell[i] = pFrom->apCell[i];
}
}
}
#define NN 1 /* Number of neighbors on either side of pPage */
#define NB (NN*2+1) /* Total pages involved in the balance */
void balance(Btree *pBt, Pool *pPool){
Pool *pParent; /* The parent of pPage */
int nCell; /* Number of cells in apCell[] */
int nOld; /* Number of pages in apOld[] */
int nNew; /* Number of pages in apNew[] */
int nDiv; /* Number of cells in apDiv[] */
int idx; /* Index of pPage in pParent->apCell[] */
int nxDiv; /* Next divider slot in pParent->apCell[] */
int subtotal; /* Subtotal of bytes in cells on one page */
Pool *extraUnref = 0; /* A page that needs to be unref-ed */
Pool *apOld[NB]; /* pPage and up to two siblings */
Pool *apNew[NB+1]; /* pPage and up to NB siblings after balancing */
int idxDiv[NB]; /* Indices of divider cells in pParent */
Cell *apDiv[NB]; /* Divider cells in pParent */
Cell aTemp[NB]; /* Temporary holding area for apDiv[] */
int cntNew[NB+1]; /* Index in apCell[] of cell after i-th page */
int szNew[NB+1]; /* Combined size of cells place on i-th page */
Pool aOld[NB]; /* Temporary copies of pPage and its siblings */
Cell *apCell[200]; /* All cells from pages being balanced */
int szCell[200]; /* Local size of all cells */
int i,j,k; /* Loop counters */
Pool* PoolOld[NB];
Pool* PoolNew[NB+1];
if( !pPool->isOverfull && pPool->nFree<512 && pPool->nCell>=2){
relinkCell(pPool);
return ;
}
pParent = pPool->pParent;
if( pParent==0 ){//
Pool *pChild;
if( pPool->nCell==0 ){
if(pPool->u.h.rightChild){
pChild=pPool->u.h.rightChild;
memcpy(pPool, pChild, 1024);
pPool->isInit = 0;
initPool(pPool,0);
reparentChild(pBt, pPool);
freePool(pBt, pChild);
}else{
relinkCell( pPool);
}
return ;
}
if( !pPool->isOverfull ){
relinkCell( pPool);
return ;
}
//分配一个新页
mallocPool(pBt, &pChild);
copyPool(pChild, pPool);
pChild->pParent = pPool;
//pChild->idxParent = 0;
pChild->isOverfull = 1;
zeroPool(pPool);
pPool->u.h.rightChild = pChild;
pParent = pPool;
pPool = pChild;
}
//到这个地方说明pPage已经不是根页了
/*
** 在parent页中查找一个Cell,他的h.leftChild指向pPage,idx就是cell的下标,
如果pPage是pParent最右边的孩子,那么设置idx为pParen->nCell
*/
for(idx=0; idx<pParent->nCell; idx++){
if( pParent->apCell[idx]->leftChild==pPool ){
break;
}
}
nOld = nNew = 0;
nxDiv = idx - NN;
if( nxDiv + NB > pParent->nCell ){
nxDiv = pParent->nCell - NB + 1;
}
if( nxDiv<0 ){
nxDiv = 0;
}
nDiv = 0;
for(i=0, k=nxDiv; i<NB; i++, k++){
if( k<pParent->nCell ){
idxDiv[i] = k;//记录下来pPool和他的兄弟们在pParent中的索引
apDiv[i] = pParent->apCell[k];//记录下来pPool和他的兄弟们在pParent中的cell
nDiv++;//记录在apDiv[]中记录的个数
PoolOld[i] = apDiv[i]->leftChild;////记录下来pPool和他的兄弟们
apOld[i]=apDiv[i]->leftChild;
}else if( k==pParent->nCell ){
apOld[i]=pParent->u.h.rightChild;
PoolOld[i]=pParent->u.h.rightChild;
}else{
break;
}
if(apOld[i]==0){
mallocPool(pBt,&apOld[i]);
}
initPool( apOld[i], pParent);
//apOld[i]->idxParent = k;
nOld++;//记录老叶的个数
}
for(i=0; i<nOld; i++){
copyPool(&aOld[i], apOld[i]);
}
nCell = 0;
for(i=0; i<nOld; i++){
Pool *pOld = &aOld[i];//保存的是老页pPage和他的兄弟的内容
for(j=0; j<pOld->nCell; j++){
apCell[nCell] = pOld->apCell[j];
szCell[nCell] = sizeof(Cell);//保存每一个Cell的大小
nCell++;
}
if( i<nOld-1 ){
szCell[nCell] =sizeof(Cell);
//???????????????????
memcpy(&aTemp[i], apDiv[i], szCell[nCell]);//把分裂的Cells拷到aTemp[]中
apCell[nCell] = &aTemp[i];
dropCell(pBt, pParent, nxDiv, szCell[nCell]);//从pParent中移出分裂的Cells
apCell[nCell]->leftChild = pOld->u.h.rightChild;
nCell++;
}
}
//将nCell个Cells分配到k个页,这不要求均匀的,前面几个页的尽量放,最后一个页或许不满
for(subtotal=k=i=0; i<nCell; i++){
subtotal += szCell[i];
if( subtotal > 1024-sizeof(PoolHead) ){
szNew[k] = subtotal - szCell[i];
cntNew[k] = i;
subtotal = 0;
k++;
}
}
szNew[k] = subtotal;
cntNew[k] = nCell;
k++;
for(i=k-1; i>0; i--){
while( szNew[i]<(1024-sizeof(PoolHead))/2 ){
cntNew[i-1]--;
szNew[i] += szCell[cntNew[i-1]];
szNew[i-1] -= szCell[cntNew[i-1]-1];
}
}
/*
** Allocate k new pages. Reuse old pages where possible.
*/
for(i=0; i<k; i++){
if( i<nOld ){
apNew[i] = apOld[i];
PoolNew[i] = PoolOld[i];
apOld[i] = 0;
}else{
mallocPool(pBt, &apNew[i]);
PoolNew[i]=apNew[i];
}
nNew++;
zeroPool( apNew[i]);
apNew[i]->isInit = 1;
}
/* Free any old pages that were not reused as new pages.
*/
while( i<nOld ){
freePool(pBt,apOld[i]);
apOld[i] = 0;
i++;
}
/*
** Evenly distribute the data in apCell[] across the new pages.
** Insert divider cells into pParent as necessary.
*/
j = 0;
for(i=0; i<nNew; i++){
Pool *pNew = apNew[i];
while( j<cntNew[i] ){
insertCell(pNew, apCell[j],pNew->nCell, szCell[j]);
j++;
}
relinkCell( pNew);
if( i<nNew-1 && j<nCell ){
pNew->u.h.rightChild = apCell[j]->leftChild;
apCell[j]->leftChild =PoolNew[i];
insertCell( pParent, apCell[j],nxDiv, szCell[j]);
j++;
nxDiv++;
}
}
apNew[nNew-1]->u.h.rightChild = aOld[nOld-1].u.h.rightChild;
if( nxDiv==pParent->nCell ){
pParent->u.h.rightChild =PoolNew[nNew-1];
}else{
pParent->apCell[nxDiv]->leftChild = PoolNew[nNew-1];
}
for(i=0; i<nNew; i++){
reparentChild(pBt, apNew[i]);
}
reparentChild(pBt, pParent);
balance(pBt, pParent);
return ;
}
void freeSpace(Btree *pBt, Pool *pPool, int start, int size){
int end = start + size;//记录一下结束的位置
u16 *pIdx;
u16 idx;
FreeBlk *pFBlk;
FreeBlk *pNew;
FreeBlk *pNext;
int iSize;
pIdx = &pPool->u.h.firstFree;//pIdx指向第一个空闲块下标
idx = *pIdx;//第一个自由块的下标
// ------------------------------------------------------------------------------------
// | PageHdr | Cell |Cell| Cell | ... | first FreeBlk |Cell|……|将要释放的空闲块
// ------------------------------------------------------------------------------------
while( idx!=0 && idx<start ){//空闲块的下标还在start之前
pFBlk = (FreeBlk*)&pPool->u.aDisk[idx];
iSize =pFBlk->iSize;//记录一下pFBlk块的大小
// ------------------------------------------------------------------------------------
// | PageHdr | Cell |Cell| Cell | ... | first FreeBlk(头部信息) |第一个空闲块|将要被释放的
//空闲块|………………
// ------------------------------------------------------------------------------------
if( idx + iSize == start ){//被释放的空闲块恰好在两个空闲块之间
pFBlk->iSize =iSize + size;
if( idx + iSize + size == pFBlk->iNext){
// ------------------------------------------------------------------------------------
// | PageHdr | Cell |Cell| Cell | ... | first FreeBlk(头部信息) |第一个空闲块|将要被释放的
//空闲块|空闲块|
// ------------------------------------------------------------------------------------
pNext = (FreeBlk*)&pPool->u.aDisk[idx + iSize + size];
pFBlk->iSize += pNext->iSize;
pFBlk->iNext = pNext->iNext;
}
// ------------------------------------------------------------------------------------
// | PageHdr | Cell |Cell| Cell | ... | first FreeBlk(头部信息) |第一个空闲块|将要被释放的
//空闲块|Cell|………………
// ------------------------------------------------------------------------------------
pPool->nFree += size;
return;
}
// ------------------------------------------------------------------------------------
// | PageHdr | Cell |Cell| Cell | ... | first FreeBlk |Cell|…|FreeBld|…|将要释放的空闲块
// ------------------------------------------------------------------------------------
//找到离将要被释放的块最近的那个块,当
pIdx = &pFBlk->iNext;
idx = *pIdx;
}
//将要被释放的空闲块
//当到这个地方的时候,将要被释放的空闲块找到了需要放的地方
pNew = (FreeBlk*)&pPool->u.aDisk[start];
if( idx != end ){//要释放的空闲块与已经在空闲表空闲块是不相邻的;
// ----------------------------------------------------------------------//将要释放的空闲块| …
//…|释放的空闲块之后的第一个自由块
// ------------------------------------------------------------------------------------
//
pNew->iSize = size;
pNew->iNext = idx;//将原来的自由块放到第二个位置
}else{//要释放的空闲块与空闲块相邻的;
// ------------------------------------------------------------------------------------
// | PageHdr | Cell |Cell| Cell | ... | first FreeBlk |Cell|…|FreeBld|…|将要释放的空闲块|
//释放的空闲块之后的第一个自由块
// ------------------------------------------------------------------------------------
pNext = (FreeBlk*)&pPool->u.aDisk[idx];//原来的自由块
pNew->iSize = size + pNext->iSize;
pNew->iNext = pNext->iNext;
}
*pIdx = start;
pPool->nFree += size;
}
void dropCell(Btree *pBt, Pool *pPool, int idx, int sz){
int j;
//删除start=Addr(pPool->apCell[idx]) - Addr(pPool),size=sz
freeSpace(pBt, pPool, Addr(pPool->apCell[idx]) - Addr(pPool), sz);
for(j=idx; j<pPool->nCell-1; j++){//仅仅维护了apCell[]
pPool->apCell[j] = pPool->apCell[j+1];
}
pPool->nCell--;
pPool->idxShift = 1;//表示apCell[]中的元素被移动过
}
int BtreeInsert(
Cursor *pCur, /* Insert data into the table of this cursor */
const void *pKey, int nKey, /* The key of the new record */
const void *pData, int nData /* The data of the new record */
){
Cell newCell;//新的Cell
int rc;//返回值
int loc;
int szNew=sizeof(newCell);
Pool* pPool;
Btree *pBt = pCur->pBt;
if( pCur->pPool==0 ){
return 0; /* A rollback destroyed this cursor */
}
//把pCur移动到pKey的位置,结果都在loc里面
loc=moveto(pCur, pKey, nKey);
pPool = pCur->pPool;
int idx=pCur->idx;
//填充一个新的Cell
fillInCell( &newCell, pKey, nKey,pData,nData);
//pCur->idx=idx;
if( loc==0 ){//准确匹配的话,删除原来的页。
newCell.leftChild= pPool->apCell[pCur->idx]->leftChild;
dropCell(pBt, pPool, pCur->idx, szNew);
}else if( loc<0 && pPool->nCell>0 ){//插入只能在页节点上做的,左孩子
//assert( pNode->u.hdr.rightChild==0 ); /* Must be a leaf page */
pCur->idx++;
}else{
//assert( pNode->u.hdr.rightChild==0 ); /* Must be a leaf page */
}
insertCell(pPool,&newCell,pCur->idx, szNew);
//printf("%d/n",*(int*)(pKey));
balance(pCur->pBt, pPool);
return rc;
}
inline int GetKey(Cell* pCell){
int x;
memcpy(&x,pCell->aPayLoad,4);
return x;
}
void Test(Pool* pPool,int high){
if(pPool==0){
return ;
}
int i;
for( i=0;i<pPool->nCell;i++){
Test(pPool->apCell[i]->leftChild,high+1);
//printf("%c/n",'c');
}
Test(pPool->u.h.rightChild,high+1);
printf("深度为%d:/n",high);
for( i=0;i<pPool->nCell;i++){
printf("%d,",GetKey(pPool->apCell[i]));
}
printf("/n%d/n",pPool->nCell);
/* for( i=0;i<pPool->nCell;i++){
if(GetKey(pPool->apCell[i])==99)
printf("%d,",GetKey(pPool->apCell[i]));*/
}
void BtreeDell(Cursor* pCur,Btree* pBt,const void * pKey,int nKey){
int rc=moveto(pCur,pKey,nKey);
if(rc==0){
dropCell(pBt, pCur->pPool, pCur->idx, sizeof(Cell));
}
}
- B,B-,B+,B*树
- B-、B、B+、B*树
- B/B+/B*树
- B- ,B+ , B*树
- B , B+ ,B*树
- B-, B+,B* 树
- B树B-B+树
- B- B+ B*树 小结
- B 、B-、B+树总结
- B-、B+、B*树介绍
- B 树、 B- 树、 B+ 树、 B*
- B树、B-树、B+树、B*
- B树,B-,B+,B*树
- B树、B-、B+、B*树
- B树,B-,B+,B* 各种树
- B,B-,B+ 和B*树
- 辨析B树(B-、B+、B*)
- B树 B+树
- exchange 2000 的邮件队列
- Framework 4.0 将何去何从
- DOM window 对象 属性 方法
- 窗口
- CRM项目上线总结--技术篇
- B树
- jquery基础
- Hebb规则试验
- 无累积误差的循环计时器
- 就 CSS3 向 Eric Meyer 请教的 6 个问题
- my.cnf修改编码
- 【JSP】JSP内置对象Cookie的用法
- 没有最好,只有更好
- 符号表