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