平衡二叉排序树便于动态查找,因此用平衡二叉排序树来组织索引表是一种可行的选择。当用于大型数据库时,所有数据及索引都存储在外存,因此,涉及到内、外存之间频繁的数据交换,这种交换速度的快慢成为制约动态查找的瓶颈。若以二叉树的结点作为内、外存之间数据交换单位,则查找给定关键字时对磁盘平均进行㏒㏒次访问是不能容忍的,因此,必须选择一种能尽可能降低磁盘I/OI/O次数的索引组织方式。树结点的大小尽可能地接近页的大小。
1,B树的数据结构,根据以上的信息,定义B树的数据结构如下:
//节点数据结构的定义
typedef struct BTNode
{
int keynum;
//节点信息的数量,不包含key[0]节点
struct BTNode *parent;
//父节点
int key[M+1];
//节点信息数组,第一个节点没用。
struct BTNode *ptr[M+1];//子节点信息
}BTNode;
typedef struct BTNode
{
}BTNode;
2,B树的查找
3,B树的插入
代码如下:
#include "stdafx.h"
#include "malloc.h"
#include "malloc.h"
#define KeyType int
#define M 3 定义B-tree 的阶数,一般是根据磁盘磁盘页的大小而定
#define M 3 定义B-tree 的阶数,一般是根据磁盘磁盘页的大小而定
typedef struct BTNode
{
int keynum; //节点信息的数量,不包含 key[0] 节点
struct BTNode *parent; //指向双亲结点
KeyType key[M+1]; //节点信息数组,第一个节点没用。因为可能有分裂,所有需要多一个key的存储
struct BTNode *ptr[M+1]; //子节点信息
//Record *recptr[m+1]; //记录指针向量
struct BTNode *next; //用于队列操作
}BTNode,*BTree; //B 树结点类型
{
int keynum; //节点信息的数量,不包含 key[0] 节点
struct BTNode *parent; //指向双亲结点
KeyType key[M+1]; //节点信息数组,第一个节点没用。因为可能有分裂,所有需要多一个key的存储
struct BTNode *ptr[M+1]; //子节点信息
//Record *recptr[m+1]; //记录指针向量
struct BTNode *next; //用于队列操作
}BTNode,*BTree; //B 树结点类型
int BT_search(BTree T,KeyType K,BTNode *&p)
{
BTNode *q;
int i;
p=q=T;
while (q!=NULL)//q==NULL说明到达最底层不含任何信息的叶子节点
{
p=q;//p指向目标节点要插入的节点
// 在节点内查找,此处可以用二分法查找
for (i=1;i<=q->keynum; i++)
{
if (K==q->key[i])//找到则不插入,直接返回位置
return i;
else if (K > q->key[i])
continue ;
else//找到插入位置
break ;
}
q=q->ptr[i-1];//q指向下一个查找节点
}
return 0;
}
// 分裂函数,当一个节点中信息数过多
// 需要分裂节点
// 参数p 为传引用
// 拆分后,分为 p和返回值 q 两个节点
BTNode *split(BTNode *&p)
{
BTNode *q;
int mid;
int j, k;
q=(BTNode *)malloc( sizeof (BTNode));//q指向右边节点
mid=(M+1)/2;
{
BTNode *q;
int i;
p=q=T;
while (q!=NULL)//q==NULL说明到达最底层不含任何信息的叶子节点
{
p=q;//p指向目标节点要插入的节点
// 在节点内查找,此处可以用二分法查找
for (i=1;i<=q->keynum; i++)
{
if (K==q->key[i])//找到则不插入,直接返回位置
return i;
else if (K > q->key[i])
continue ;
else//找到插入位置
break ;
}
q=q->ptr[i-1];//q指向下一个查找节点
}
return 0;
}
// 分裂函数,当一个节点中信息数过多
// 需要分裂节点
// 参数p 为传引用
// 拆分后,分为 p和返回值 q 两个节点
BTNode *split(BTNode *&p)
{
BTNode *q;
int mid;
int j, k;
q=(BTNode *)malloc( sizeof (BTNode));//q指向右边节点
mid=(M+1)/2;
q->ptr[0]=p->ptr[mid];
if (q->ptr[0] != NULL)
q->ptr[0]->parent=q;
// 从mid 位置拆分, mid 值上调到父节点
// mid 后为一部分, mid前为一部分
for (j=1, k=mid+1; k<=M; j++,k++)
{
q->key[j]=p->key[k];
q->ptr[j]=p->ptr[k];
q->ptr[0]->parent=q;
// 从mid 位置拆分, mid 值上调到父节点
// mid 后为一部分, mid前为一部分
for (j=1, k=mid+1; k<=M; j++,k++)
{
q->key[j]=p->key[k];
q->ptr[j]=p->ptr[k];
if (q->ptr[j] != NULL)
q->ptr[j]->parent=q; // 注意此处拆分后,要修改父节点信息。
}
q->keynum=M-mid;
p->keynum=mid-1;
q->parent=p->parent;
return q;
}
// 插入节点,参数 T为父节点, K 为插入信息
void insert_BTree(BTNode *&T, int K)
{
int i;
BTNode *p=NULL, *s1=NULL, *s2=NULL;
q->ptr[j]->parent=q; // 注意此处拆分后,要修改父节点信息。
}
q->keynum=M-mid;
p->keynum=mid-1;
q->parent=p->parent;
return q;
}
// 插入节点,参数 T为父节点, K 为插入信息
void insert_BTree(BTNode *&T, int K)
{
int i;
BTNode *p=NULL, *s1=NULL, *s2=NULL;
if (!BT_search(T, K, p))//没找到这个节点,可以插入
{
while (p!=NULL)
{
p->key[0]=K;//哨兵
for (i=p->keynum; K<p->key[i];i--) //直接插入排序思想
{
p->key[i+1]=p->key[i];
p->ptr[i+1]=p->ptr[i];
}
p->key[i+1]=K;
p->ptr[i+1]=s2;
p->ptr[i]=s1;
{
while (p!=NULL)
{
p->key[0]=K;//哨兵
for (i=p->keynum; K<p->key[i];i--) //直接插入排序思想
{
p->key[i+1]=p->key[i];
p->ptr[i+1]=p->ptr[i];
}
p->key[i+1]=K;
p->ptr[i+1]=s2;
p->ptr[i]=s1;
if (++(p->keynum) < M) //插入结束
break;
else
{
s2=split(p);
s1=p;
K=p->key[p->keynum+1];//要插入到父节点的那个元素
p=p->parent;
}
if (p==NULL)//根节点无父节点
{
p=(BTNode *)malloc( sizeof (BTNode));
p->keynum=1;
p->key[1]=K;
p->ptr[0]=s1;
s1->parent=p;
p->ptr[1]=s2;
s2->parent=p;
p->parent=NULL;
T=p;
break;
}//if
}//while
}
}
//
break;
else
{
s2=split(p);
s1=p;
K=p->key[p->keynum+1];//要插入到父节点的那个元素
p=p->parent;
}
if (p==NULL)//根节点无父节点
{
p=(BTNode *)malloc( sizeof (BTNode));
p->keynum=1;
p->key[1]=K;
p->ptr[0]=s1;
s1->parent=p;
p->ptr[1]=s2;
s2->parent=p;
p->parent=NULL;
T=p;
break;
}//if
}//while
}
}
//
typedef struct// 链式队列
{
BTNode *front,*rear;
}LiQueue;
{
BTNode *front,*rear;
}LiQueue;
void InitQueue(LiQueue &Q)
{
Q.front=Q.rear=(BTNode*)malloc(sizeof(BTNode));//建立头结点
Q.front->next=NULL;
}
{
Q.front=Q.rear=(BTNode*)malloc(sizeof(BTNode));//建立头结点
Q.front->next=NULL;
}
bool QueueEmpty(LiQueue Q)
{
if (Q.rear==Q.front)
return true;
else
return false;
}
void EnQueue(LiQueue &Q,BTNode * s)
{
s->next=NULL;//创建新节点,插入到链尾
Q.rear->next=s;
Q.rear=s;
}
bool DeQueue(LiQueue &Q)
{//Q.front一直指向头结点
if (Q.front==Q.rear)//空队
return false;
{
if (Q.rear==Q.front)
return true;
else
return false;
}
void EnQueue(LiQueue &Q,BTNode * s)
{
s->next=NULL;//创建新节点,插入到链尾
Q.rear->next=s;
Q.rear=s;
}
bool DeQueue(LiQueue &Q)
{//Q.front一直指向头结点
if (Q.front==Q.rear)//空队
return false;
BTNode* s=Q.front->next;
Q.front->next=s->next;
if (Q.rear==s)//若队列中只有一个结点,删除后变空
Q.rear=Q.front;
free(s);
return true;
}
//
// 借助队列层次遍历函数,用于检验 b-tree 正确性。
void mid_order(BTNode *T)
{
int i;
LiQueue Q;
InitQueue(Q);
if (Q.rear==s)//若队列中只有一个结点,删除后变空
Q.rear=Q.front;
free(s);
return true;
}
//
// 借助队列层次遍历函数,用于检验 b-tree 正确性。
void mid_order(BTNode *T)
{
int i;
LiQueue Q;
InitQueue(Q);
BTNode *p=T;
if (p!=NULL)
{
EnQueue(Q,p);
while (!QueueEmpty(Q))
{
p=Q.front->next;
for (i=0; i<=p->keynum; i++)
{
if (p->ptr[i] != NULL)
EnQueue(Q,p->ptr[i]);
if (i!=p->keynum)
printf("%d ",p->key[i+1]);
}
DeQueue(Q);
}
printf("\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
KeyType k[7]={20,30,50,52,60,68,70};
if (p!=NULL)
{
EnQueue(Q,p);
while (!QueueEmpty(Q))
{
p=Q.front->next;
for (i=0; i<=p->keynum; i++)
{
if (p->ptr[i] != NULL)
EnQueue(Q,p->ptr[i]);
if (i!=p->keynum)
printf("%d ",p->key[i+1]);
}
DeQueue(Q);
}
printf("\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
KeyType k[7]={20,30,50,52,60,68,70};
int i;
//int num;
//int num;
BTNode *T=NULL;
//BTNode *p;
//BTNode *p;
for (i=0; i<7;i++)
{
if (T==NULL)
{
T=(BTNode *)malloc( sizeof (BTNode));
T->keynum=1;
T->key[1]=k[i];
T->ptr[0]=NULL;
T->ptr[1]=NULL;
T->parent=NULL;
}
else
{
insert_BTree(T, k[i]);
}
}
mid_order(T);
return 0;
}
{
if (T==NULL)
{
T=(BTNode *)malloc( sizeof (BTNode));
T->keynum=1;
T->key[1]=k[i];
T->ptr[0]=NULL;
T->ptr[1]=NULL;
T->parent=NULL;
}
else
{
insert_BTree(T, k[i]);
}
}
mid_order(T);
return 0;
}