B-树代码实现

本文介绍了一个B树的数据结构实现,包括初始化、插入、查找等核心功能,并详细解释了节点分裂的过程。通过对B树的操作,实现了对文件中用户信息的有效管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 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);
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值