BTree.h
#include <stdio.h>
#define M 11
typedef struct
{
char PhoneNo[14];
char Name[10];
char Addr[16];
char Kind[24];
}UserInfo;//结构体大小64字节
typedef char TypeKey[12];
typedef struct Node{
int KeyNum;
long FilePos[M];
TypeKey Key[M];
struct Node *Parent;
struct Node *PtrSon[M + 1];
}TreeNode, *BTree;
char * InsValue; /* 与要插的键相对应的值 */
void InitBTree(BTree*);
UserInfo* SearchUser(TypeKey, BTree);
void InsertUser(TypeKey _key, long _filePos, BTree*);
void VisitBTree(TreeNode*);
void SetPrevKey();
BTree.c
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "BTree.h"
TypeKey gPrevKey = "00000000000";
int Compare(TypeKey _srcKey, TypeKey _destKey)
{
TypeKey srcKey = {0};
TypeKey destKey = {0};
int keyIndex = 0;
strcpy(srcKey, _srcKey);
strcpy(destKey, _destKey);
if(NULL == srcKey && NULL == destKey)
{
return 0;
}
if(NULL == srcKey && NULL != destKey)
{
return -1;
}
if(NULL != srcKey && NULL == destKey)
{
return 1;
}
for(keyIndex = 0; keyIndex < 11; keyIndex++)
{
if(0 == srcKey[keyIndex] && 0 == destKey[keyIndex])
{
return 0;
}
if(0 == srcKey[keyIndex] && 0 != destKey[keyIndex])
{
return -1;
}
if(0 != srcKey[keyIndex] && 0 == destKey[keyIndex])
{
return 1;
}
if(srcKey[keyIndex] == destKey[keyIndex])
{
continue;
}
else
{
return srcKey[keyIndex] > destKey[keyIndex] ? 1 : -1;
}
}
return 0;
}
void SetPrevKey()
{
strcpy(gPrevKey, "00000000000");
}
void VisitBTree(TreeNode *_node)
{
TreeNode *treeNode = _node;
TreeNode *parentNode = NULL;
TypeKey prevKey = {0};
int keyIndex = 0;
parentNode = treeNode->Parent;
if(NULL != parentNode)
{
int index;
for(index = 0; index < (parentNode->KeyNum + 1); index++)
{
if(treeNode == parentNode->PtrSon[index])
{
break;
}
}
assert(index != (parentNode->KeyNum + 1));
}
for(keyIndex = 0; keyIndex < treeNode->KeyNum; keyIndex++)
{
if(NULL != treeNode->PtrSon[keyIndex])
{
VisitBTree(treeNode->PtrSon[keyIndex]);
}
//printf("%s/t%d/n", treeNode->Key[keyIndex], treeNode->FilePos[keyIndex]);
if(Compare(gPrevKey, treeNode->Key[keyIndex]) > 0)
{
printf("Exception!/n");
}
strcpy(gPrevKey, treeNode->Key[keyIndex]);
}
if(NULL != treeNode->PtrSon[keyIndex])
{
VisitBTree(treeNode->PtrSon[keyIndex]);
}
else
{
assert(NULL == treeNode->PtrSon[keyIndex - 1]);
}
}
UserInfo* SearchUser(TypeKey _key, BTree _tree)
{
TypeKey searchKey = {0};
TreeNode *pNode = _tree;
UserInfo *pUserInfo = NULL;
int keyIndex = 0;
int compareRes = 0;
int bFound = 0;
strcpy(searchKey, _key);
while(!bFound)
{
if(NULL == pNode)
{
break;
}
for(keyIndex = 0; keyIndex < pNode->KeyNum; keyIndex++)
{
compareRes = Compare(searchKey, pNode->Key[keyIndex]);
if(compareRes < 0)
{
pNode = pNode->PtrSon[keyIndex];
break;
}
else
{
printf("%s/n", pNode->Key[keyIndex]);
if(0 == compareRes)
{
bFound = 1;
break;
}
}
}
if(NULL != pNode && keyIndex == pNode->KeyNum)
{
pNode = pNode->PtrSon[keyIndex];
}
}
if(bFound)
{
long readLen = 0L;
char readBuf[64 + 1] = {0};
char fieldPhone[15] = {0};
char fieldName[10] = {0};
char fieldAddr[20] = {0};
char fieldKind[30] = {0};
char *pFieldBegin = NULL;
char *pFieldEnd = NULL;
char *pFieldSep = NULL;
FILE *pUserFile;
pUserFile = fopen("userinfo.txt","r");
fseek(pUserFile, pNode->FilePos[keyIndex], SEEK_SET);
readLen = fread(readBuf, 1, 64, pUserFile);
readBuf[readLen] = 0;
//字段1--手机号码
pFieldBegin = readBuf;
pFieldSep = strstr(pFieldBegin, "|");
if(NULL == pFieldSep)
{
return NULL;
}
pFieldEnd = pFieldSep - 1;
strncpy(fieldPhone, pFieldBegin, pFieldEnd - pFieldBegin + 1);
//字段2--用户姓名
pFieldBegin = pFieldSep + 1;
pFieldSep = strstr(pFieldBegin, "|");
if(NULL == pFieldSep)
{
return NULL;
}
pFieldEnd = pFieldSep - 1;
strncpy(fieldName, pFieldBegin, pFieldEnd - pFieldBegin + 1);
//字段3--号码归属地
pFieldBegin = pFieldSep + 1;
pFieldSep = strstr(pFieldBegin, "|");
if(NULL == pFieldSep)
{
return NULL;
}
pFieldEnd = pFieldSep - 1;
strncpy(fieldAddr, pFieldBegin, pFieldEnd - pFieldBegin + 1);
//字段4--号码类型
pFieldBegin = pFieldSep + 1;
pFieldSep = strstr(pFieldBegin, "/n");
if(NULL == pFieldSep)
{
return NULL;
}
pFieldEnd = pFieldSep - 1;
strncpy(fieldKind, pFieldBegin, pFieldEnd - pFieldBegin + 1);
pUserInfo = (UserInfo*)malloc(sizeof(UserInfo));
strcpy(pUserInfo->PhoneNo, fieldPhone);
strcpy(pUserInfo->Name, fieldName);
strcpy(pUserInfo->Addr, fieldAddr);
strcpy(pUserInfo->Kind, fieldKind);
return pUserInfo;
}
else
{
return NULL;
}
}
void InitBTree(BTree *pBTree)
{
int index = 0;
TreeNode *pHeadNode;
*pBTree = (TreeNode*)malloc(sizeof(TreeNode));
memset(*pBTree, 0, sizeof(TreeNode));
pHeadNode = *pBTree;
pHeadNode->Parent = NULL;
pHeadNode->KeyNum = 0;
}
void SplitNode(TreeNode *_pNode, TreeNode **_treeNode)
{
TreeNode **pBTree = _treeNode;
TreeNode *pOriginalNode = _pNode;
TreeNode *pParentNode = NULL;
TreeNode *pNewNode = NULL;
int keyIndex = 0;
int sepPosIdx = (M - 1) / 2;
long tmpFilePos = 0L;
long insFilePos = 0L;
TypeKey tmpKey = {0};
TypeKey insKey = {0};
TreeNode *pTmpSon = NULL;
TreeNode *pInsSon = NULL;
while(pOriginalNode->KeyNum >= M)
{
//printf("Before Split new node*******************************/n");
VisitBTree(*pBTree);
//如果根节点满了,则添加新的根节点
if(NULL == pOriginalNode->Parent)
{
pOriginalNode->Parent = (TreeNode*)malloc(sizeof(TreeNode));
memset(pOriginalNode->Parent, 0, sizeof(TreeNode));
*pBTree = pOriginalNode->Parent;
(*pBTree)->Parent = NULL;
(*pBTree)->KeyNum = 0;
(*pBTree)->PtrSon[0] = pOriginalNode;
}
pNewNode = (TreeNode*)malloc(sizeof(TreeNode));
memset(pNewNode, 0, sizeof(TreeNode));
if(0 == Compare(pOriginalNode->Key[sepPosIdx], "13172530000"))
{
int i;
//printf("%s/n", pOriginalNode->Key[sepPosIdx]);
}
//构造新节点
pNewNode->Parent = pOriginalNode->Parent;
for(keyIndex = sepPosIdx + 1; keyIndex < M; keyIndex++)
{
pNewNode->FilePos[keyIndex - (sepPosIdx + 1)] = pOriginalNode->FilePos[keyIndex];
strcpy(pNewNode->Key[keyIndex - (sepPosIdx + 1)], pOriginalNode->Key[keyIndex]);
pNewNode->PtrSon[keyIndex - (sepPosIdx + 1)] = pOriginalNode->PtrSon[keyIndex];
if(NULL != pNewNode->PtrSon[keyIndex - (sepPosIdx + 1)])
{
pNewNode->PtrSon[keyIndex - (sepPosIdx + 1)]->Parent = pNewNode;
}
pNewNode->KeyNum++;
}
pNewNode->PtrSon[keyIndex - (sepPosIdx + 1)] = pOriginalNode->PtrSon[keyIndex];
if(NULL != pNewNode->PtrSon[keyIndex - (sepPosIdx + 1)])
{
pNewNode->PtrSon[keyIndex - (sepPosIdx + 1)]->Parent = pNewNode;
}
//上移分裂子节点中的一个值到父节点
pParentNode = pOriginalNode->Parent;
insFilePos = pOriginalNode->FilePos[sepPosIdx];
strcpy(insKey, pOriginalNode->Key[sepPosIdx]);
pInsSon = pNewNode;
//printf("Move upwards node [%s], file position [%d]!/n", insKey, insFilePos);
//(KeyNum + 1)个子节点
for(keyIndex = 0; keyIndex < (pParentNode->KeyNum + 1); keyIndex++)
{
if(pOriginalNode == pParentNode->PtrSon[keyIndex])
{
break;
}
}
//(KeyNum + 1)个键
for(; keyIndex < (pParentNode->KeyNum + 1); keyIndex++)
{
strcpy(tmpKey, pParentNode->Key[keyIndex]);
strcpy(pParentNode->Key[keyIndex], insKey);
strcpy(insKey, tmpKey);
tmpFilePos = pParentNode->FilePos[keyIndex];
pParentNode->FilePos[keyIndex] = insFilePos;
insFilePos = tmpFilePos;
pTmpSon = pParentNode->PtrSon[keyIndex + 1];
pParentNode->PtrSon[keyIndex + 1] = pInsSon;
pInsSon = pTmpSon;
}
pParentNode->KeyNum++;
pOriginalNode->KeyNum = pOriginalNode->KeyNum - 1 - pNewNode->KeyNum;
for(keyIndex = pOriginalNode->KeyNum; keyIndex < M; keyIndex++)
{
pOriginalNode->FilePos[keyIndex] = -1L;
strcpy(pOriginalNode->Key[keyIndex], "00000000000");
pOriginalNode->PtrSon[keyIndex + 1] = NULL;
}
pOriginalNode->PtrSon[M] = NULL;
pOriginalNode = pOriginalNode->Parent;
//printf("After Split new node*******************************/n");
VisitBTree(*pBTree);
}
}
void InsertLeafNode(TypeKey _key, long _filePos, int _insIndex, TreeNode *_pNode, TreeNode **_bTree)
{
TypeKey insKey = {0};
long insFilePos = _filePos;
int insIndex = _insIndex;
TreeNode *pNode = _pNode;
TreeNode **pBTree = _bTree;
int index = 0;
long tmpFilePos = -1L;
TypeKey tmpKey = {0};
strcpy(insKey, _key);
for(index = insIndex; index < pNode->KeyNum; index++)
{
tmpFilePos = pNode->FilePos[index];
pNode->FilePos[index] = insFilePos;
insFilePos = tmpFilePos;
strcpy(tmpKey, pNode->Key[index]);
strcpy(pNode->Key[index], insKey);
strcpy(insKey, tmpKey);
}
pNode->FilePos[index] = insFilePos;
strcpy(pNode->Key[index], insKey);
pNode->KeyNum++;
if(M == pNode->KeyNum)
{
SplitNode(pNode, pBTree);
}
}
void InsertUser(TypeKey _key, long _filePos, TreeNode **_treeNode)
{
int keyIndex = 0;
int compareRes = 0;
TypeKey key = {0};
long filePos = _filePos;
TreeNode **pBTree = _treeNode;
TreeNode *pNode = *_treeNode;
int bFound = 0;
strcpy(key, _key);
if(0 == Compare(key, "13267260000"))
{
int i;
//printf("%s/n", key);
}
while(!bFound)
{
for(keyIndex = 0; keyIndex < pNode->KeyNum; keyIndex++)
{
compareRes = Compare(key, pNode->Key[keyIndex]);
if(compareRes < 0)
{
break;
}
}
if(compareRes >= 0)
{
assert(keyIndex == pNode->KeyNum);
}
if(compareRes < 0)
{
if(NULL == pNode->PtrSon[keyIndex])
{
bFound = 1;
}
else
{
pNode = pNode->PtrSon[keyIndex];
}
}
else
{
if(NULL != pNode->PtrSon[keyIndex])
{
pNode = pNode->PtrSon[keyIndex];
}
else
{
bFound = 1;
}
}
}
assert(bFound);
{
int index = 0;
for(;index < pNode->KeyNum + 1;index++)
{
assert(NULL == pNode->PtrSon[index]);
}
}
InsertLeafNode(key, filePos, keyIndex, pNode, pBTree);
}