1. 程式人生 > >B+樹演算法與原始碼(C語言描述)

B+樹演算法與原始碼(C語言描述)

B+樹可以看作是B樹的變形,對於存放在外存貯器上的字典,B+樹比B樹更為常用。

  一個m階的B+樹滿足下列條件∶

  (1) 每個結點至多有m棵子樹。

  (2) 除根結點外,其它每個分支至少有m/2棵子樹。

  (3) 非葉結點的根結點至少有兩棵子樹。

  (4) 有n棵子樹的結點有n個關鍵碼,葉結點中至少包含n/2個關鍵碼。

  (5) 葉結點都在同一層中,其中存放資料檔案中記錄的關鍵碼及指向該記錄的指標,或存放資料檔案分塊後每塊的最大關鍵碼及指向該塊的指標。葉結點按關鍵碼值大小 順序連結。可以把每個葉結點看成是一個基本索引塊(直接指向資料檔案中的記錄)。

  (6) 所有分支結點可看成是索引的索引。使結點中僅包含它的各個子結點中最大(或最小)關鍵碼的分界值及指向子結點的指標。

/*=========================== BinTreeh.h =========================*/

#include <stdio.h>
/*=========================== data struct =====================*/

typedef char ElementType;
typedef struct Node{
ElementType data;
struct Node *LChild; /* 左子樹 */
struct Node *RChild; /* 右子樹*/
} TreeNode;
/*=============================== function prounce ===============*/

int CreateBinTree( TreeNode **rootp,ElementType **lp );
void FreeTree( TreeNode *rootp );

int DelTree( TreeNode *rootp,ElementType e );
int Insert( TreeNode *rootp,ElementType Curr,ElementType e,int CurrPos );

TreeNode *FindNode( TreeNode *rootp,ElementType e );
TreeNode *FindParent( TreeNode *rootp,ElementType e );

void Leaf( TreeNode *rootp,int *np );
int Depth( TreeNode *rootp );

void PreOrder( TreeNode *rootp );
void MidOrder( TreeNode *rootp );
void BackOrder( TreeNode *rootp );
/*================================ function body ================*/

/*------------------------------------   建樹 -------------------------*/
int CreateBinTree( TreeNode **rootp,ElementType **lp )
{
ElementType CurrElement;

if(*lp==NULL) return 0; /*    字串不存在,返回 0 */
if(**lp==0) return 1; /*    字串為空,返回1      */
CurrElement=*(*lp);
(*lp)++;
if(CurrElement=='.') { (*rootp)=NULL; return 1; }
if(!((*rootp)=(TreeNode *) malloc(sizeof(TreeNode))) ) return 0;
(*rootp)->data=CurrElement;
if(!CreateBinTree(&(*rootp)->LChild,lp)) return 0;
return CreateBinTree(&(*rootp)->RChild,lp);
}
/*-------------------------------------------------------   前序遍歷子樹--------*/
void PreOrder( TreeNode *rootp )
{
if(rootp==NULL) return;
printf(" %c",rootp->data); /*    列印父節點            */
if(rootp->LChild!=NULL) PreOrder(rootp->LChild); /*   列印左子樹節點*/
if(rootp->RChild!=NULL) PreOrder(rootp->RChild); /*   列印右子樹節點 */
return;
}
/*--------------------------------------------------------   中序遍歷子樹 --------*/
void MidOrder( TreeNode *rootp )
{
if(rootp==NULL) return;
if(rootp->LChild!=NULL) MidOrder(rootp->LChild);
printf(" %c",rootp->data);
if(rootp->RChild!=NULL) MidOrder(rootp->RChild);
return;
}
/*------------------------------------------------------ 後序遍歷子樹--------*/
void BackOrder( TreeNode *rootp )
{
if(rootp==NULL) return;
if(rootp->LChild!=NULL) BackOrder(rootp->LChild);
if(rootp->RChild!=NULL) BackOrder(rootp->RChild);
printf(" %c",rootp->data);
return;
}
/*-------------------------------------------------------   查詢節點--------*/
TreeNode *FindNode( TreeNode *rootp,ElementType e )
{
TreeNode *temp;

if(rootp==NULL) return NULL; /*    根節點為空,沒有找到(空樹) */
if(rootp->data==e) return rootp;
if(temp=FindNode(rootp->LChild,e)) return temp;
return FindNode(rootp->RChild,e);
}
/*-------------------------------------------------------    釋放樹所佔記憶體空間   --------*/
void FreeTree( TreeNode *rootp )
{
if(!rootp) return;
FreeTree(rootp->LChild);
FreeTree(rootp->RChild);
free(rootp);
}
/*-----------------------------------------------------   查詢父節點--------*/
TreeNode *FindParent( TreeNode *rootp,ElementType e )
{
TreeNode *temp;

if((rootp==NULL)||(rootp->LChild==NULL && rootp->RChild==NULL)) return NULL;
if((rootp->LChild && rootp->LChild->data==e)
||(rootp->RChild && rootp->RChild->data==e)) return rootp;
temp=FindParent(rootp->LChild,e);
if(temp) return temp;
return FindParent(rootp->RChild,e);
}
/*--------------------------------------------------------    刪除樹節點   --------*/
int DelTree( TreeNode *rootp,ElementType e )
{
TreeNode *temp;

temp=FindParent(rootp,e);
if(!temp) return 0;
if(temp->LChild &&(temp->LChild->data==e))
{ FreeTree(temp->LChild);
temp->LChild=NULL;
}
else
{ FreeTree(temp->RChild);
temp->RChild=NULL;
}
return 1;
}
/*--------------------------------------------------------   插入節點--------*/
int Insert( TreeNode *rootp,ElementType Curr,ElementType e,int CurrPos )
{
TreeNode *parent,*new,*temp;

if(!(parent=FindParent(rootp,Curr))) return 0;
if(!(new=(TreeNode *) malloc(sizeof(TreeNode)))) return 0;
new->data=e;
if(parent->LChild->data==Curr) { temp=parent->LChild; parent->LChild=new; }
temp=parent->RChild;
parent->RChild=new;

if(CurrPos==0) new->LChild=temp; new->RChild=NULL;
if(CurrPos==1) new->RChild=temp; new->LChild=NULL;

return 1;
}
/*-----------------------------------------------------------    計算葉子節點 --------*/
void Leaf( TreeNode *rootp,int *np )
{
if(rootp==NULL) return ;
if(rootp->LChild==NULL && rootp->RChild==NULL) { (*np)++; return; }
Leaf(rootp->LChild,np);
Leaf(rootp->RChild,np);
}
/*----------------------------------------------------------   計算樹高--------*/
int Depth( TreeNode *rootp )
{
int ld,rd; /* ld:左子樹深度*/
             /* rd: 右子樹深度*/
if(rootp==NULL) return 0;
ld=Depth(rootp->LChild);
rd=Depth(rootp->RChild);
if(ld>rd) return ld+1;
else return rd+1;
}
/*=========================== The end of BinTreeh.h ======================*/

RE:如有註釋錯誤請指正,演算法很奇妙,希望共同探討,共同進步……

http://hi.baidu.com/qd_dyf/blog/item/ccc32f23e311e6ad4723e858.html