【 日常 】 二三查找树 17年4月06日22:22 [ 6 ]

/* 前言: 好多天前准备记录下自己的坎坷修仙的点滴,以后希望能留下【珍贵的回忆】,萌新的日常代码,大佬互喷*/

代码写的比较繁琐,多多见谅,萌新每天都在努力改变自己

2-3树的代码比较坑,网上基本找不到参考 ( 功能不全还差删除 )只能自己乱想 QaQ

# include <stdio.h>
# include <malloc.h>
# include <stdlib.h>
# define N 3
struct BTreeNode
{
	int data[N];//结点从0开始压,到2满
	int CurrentSize;
	BTreeNode*pChild[N + 1];//指针从0开始压
	BTreeNode*pParent;
};

void InitBTreeNode(BTreeNode*&, BTreeNode*&, BTreeNode*, int);
bool NoAppear(BTreeNode*, int);
bool NoChild(BTreeNode*);
bool NoFull(BTreeNode*);
void Insert(BTreeNode*, BTreeNode*, int);//将值插入结点
void InitpRootNodeLeft(BTreeNode*, int);//初始化左分裂树
void InitpRootNodeRight(BTreeNode*&, BTreeNode*);//初始化分裂右子树
void TravelBTreeNode(BTreeNode*);//遍历
void SplitTreeNode(BTreeNode*&, BTreeNode*, int);//分裂函数
void CreatNewRoot(BTreeNode*&, BTreeNode*, BTreeNode*);//创建新根
BTreeNode* SearchInformation(BTreeNode*, int);
int main(void)
{
	BTreeNode*pRoot = NULL;
	BTreeNode*pResearch = NULL;
	InitBTreeNode(pRoot, pRoot, NULL, 3);
	InitBTreeNode(pRoot, pRoot, NULL, 1);
	InitBTreeNode(pRoot, pRoot, NULL, 7);
	InitBTreeNode(pRoot, pRoot, NULL, 9);
	InitBTreeNode(pRoot, pRoot, NULL, 2);
	InitBTreeNode(pRoot, pRoot, NULL, 17);
	InitBTreeNode(pRoot, pRoot, NULL, 13);
	InitBTreeNode(pRoot, pRoot, NULL, 12);
	InitBTreeNode(pRoot, pRoot, NULL, 11);
	InitBTreeNode(pRoot, pRoot, NULL, 14);
	InitBTreeNode(pRoot, pRoot, NULL, 15);
	InitBTreeNode(pRoot, pRoot, NULL, 16);
	InitBTreeNode(pRoot, pRoot, NULL, 4);
	InitBTreeNode(pRoot, pRoot, NULL, 5);
	InitBTreeNode(pRoot, pRoot, NULL, 6);
	InitBTreeNode(pRoot, pRoot, NULL, 33);
	InitBTreeNode(pRoot, pRoot, NULL, 31);
	InitBTreeNode(pRoot, pRoot, NULL, 30);
	InitBTreeNode(pRoot, pRoot, NULL, 27);
	InitBTreeNode(pRoot, pRoot, NULL, 25);
	InitBTreeNode(pRoot, pRoot, NULL, 26);
	InitBTreeNode(pRoot, pRoot, NULL, 36);

	int SearchNum = 14;		//要查找的数
	pResearch = SearchInformation(pRoot, SearchNum);
	for (int i = 0; i < pResearch->CurrentSize; ++i)
		if (pResearch->data[i] == SearchNum)
			printf("查找到的数:%d\n\n", pResearch->data[i]);
	TravelBTreeNode(pRoot);
	system("pause");
	return 0;
}
void InitBTreeNode(BTreeNode*&pROOT, BTreeNode*&pRoot, BTreeNode*pParent, int InitNum)
{
	if (!pRoot)
	{
		pRoot = (BTreeNode*)malloc(sizeof(BTreeNode));
		if (!pRoot)
		{
			printf("\nERROR:初始化内存失败\n");
			exit(-1);
		}
		pRoot->CurrentSize = 0;
		pRoot->data[pRoot->CurrentSize++] = InitNum;//长度自增
		pRoot->pParent = pParent;
		for (int i = 0; i < N + 1; ++i)
			pRoot->pChild[i] = NULL;
	}
	else if (NoAppear(pRoot, InitNum))//当前结点没出现
	{
		if (NoChild(pRoot))//该结点没孩子
		{
			Insert(pRoot, NULL, InitNum);//将值先插入3-Node 变成 4-Node
			if (!NoFull(pRoot))//满
				SplitTreeNode(pROOT, pRoot, InitNum);
		}
		else
		{
			int i = 0;
			for (i; i < pRoot->CurrentSize; ++i)
				if (InitNum < pRoot->data[i])
					break;
			InitBTreeNode(pROOT, pRoot->pChild[i], pRoot, InitNum);//正确的位置接受
		}
	}
	/*---------------------------------
	else已有  do nothing
	----------------------------------*/
}
void Insert(BTreeNode*pRoot, BTreeNode*pNewPosition, int InitNum)
{
	int i = pRoot->CurrentSize;
	for (i; i > 0; --i)
		if (pRoot->data[i - 1] > InitNum)
		{
			pRoot->data[i] = pRoot->data[i - 1];//数据域后移
			pRoot->pChild[i + 1] = pRoot->pChild[i];//指针域后移
			if (pRoot->pChild[i])//如果有孩子,修改孩子的父亲
				pRoot->pChild[i]->pParent = pRoot;
		}
		else
			break;
	pRoot->data[i] = InitNum;
	pRoot->pChild[i + 1] = pNewPosition;
	if (pNewPosition)
		pNewPosition->pParent = pRoot;//赋值父亲
	pRoot->CurrentSize++;
}
void SplitTreeNode(BTreeNode*&pROOT, BTreeNode*pRoot, int InitNum)
{
	int mid = N / 2;//分裂点
	BTreeNode*pSplitRightNode = NULL;//split Right Node
	InitpRootNodeRight(pSplitRightNode, pRoot);//split Left Node
	InitpRootNodeLeft(pRoot, mid);
	//Up to search parent
	if (pRoot->pParent)
	{
		Insert(pRoot->pParent, pSplitRightNode, pRoot->data[mid]);
		if (!NoFull(pRoot->pParent))//如果满
			SplitTreeNode(pROOT, pRoot->pParent, pRoot->data[mid]);//父亲满继续分裂
	}
	else
		CreatNewRoot(pROOT, pRoot, pSplitRightNode);//重新分裂个新根
}
void CreatNewRoot(BTreeNode*&pROOT, BTreeNode*pSplitLeftNode, BTreeNode*pSplitRightNode)
{
	int mid = N / 2;//分裂点
					//创建新根结点
	BTreeNode*pNewRoot = (BTreeNode*)malloc(sizeof(BTreeNode));
	if (!pNewRoot)
	{
		printf("\nERROR:Out of Space\n");
		exit(-1);
	}
	for (int i = 0; i < N + 1; ++i)//新根指针初始化
		pNewRoot->pChild[i] = NULL;
	pNewRoot->CurrentSize = 0;
	pNewRoot->data[pNewRoot->CurrentSize++] = pSplitLeftNode->data[mid];//原pRoot的mid做根值
	pNewRoot->pChild[pNewRoot->CurrentSize - 1] = pSplitLeftNode;//左指原根
	pNewRoot->pChild[pNewRoot->CurrentSize] = pSplitRightNode;//右指新根
	pNewRoot->pParent = NULL;
	pSplitLeftNode->pParent = pNewRoot;//原根的父亲是新根
	pSplitRightNode->pParent = pNewRoot;//分裂右根父亲也是新根
	pROOT = pNewRoot;//引用根指针指向该结点
}
void InitpRootNodeRight(BTreeNode*&pSplitRightNode, BTreeNode*pSplitLeftNode)
{
	pSplitRightNode = (BTreeNode*)malloc(sizeof(BTreeNode));
	if (!pSplitRightNode)
	{
		printf("\nOut of Space\n");
		exit(-1);
	}
	for (int temp = 0; temp < N + 1; ++temp)//指针域初始化NULL
		pSplitRightNode->pChild[temp] = NULL;
	int mid = N / 2;
	pSplitRightNode->CurrentSize = 0;
	int k = 0;
	int j;
	for (j = mid + 1; j < N; ++j)//mid's right to pNewNode
	{
		pSplitRightNode->data[k] = pSplitLeftNode->data[j];//拷贝数据域
		pSplitRightNode->pChild[k++] = pSplitLeftNode->pChild[j];//拷贝指针域  
		if (pSplitLeftNode->pChild[j])//如果孩子存在
			pSplitLeftNode->pChild[j]->pParent = pSplitRightNode;
		pSplitRightNode->CurrentSize++;
	}
	pSplitRightNode->pChild[k++] = pSplitLeftNode->pChild[j];//拷贝指针域
	if (pSplitLeftNode->pChild[j])//如果孩子存在
		pSplitLeftNode->pChild[j]->pParent = pSplitRightNode;
}
void InitpRootNodeLeft(BTreeNode*pRoot, int mid)
{
	for (int i = mid + 1; i < N + 1; ++i)
		pRoot->pChild[i] = NULL;
	pRoot->CurrentSize = pRoot->CurrentSize - mid - 1;
}
BTreeNode* SearchInformation(BTreeNode*pRoot,int SearchNum)
{
	if (!pRoot)
		return pRoot;
	BTreeNode*pSentinel = pRoot;
	int i;
	while (pSentinel)//当哨兵存在
	{
		for (i = 0; i < pSentinel->CurrentSize; i++)
			if (SearchNum < pSentinel->data[i])
				break;
			else if (SearchNum == pSentinel->data[i])
				return pSentinel;
		pSentinel = pSentinel->pChild[i];
	}
	return pSentinel;
}
void TravelBTreeNode(BTreeNode*pRoot)
{
	if (!pRoot)
		return;
	for (int j = 0; j < pRoot->CurrentSize; ++j)
		printf("%d\t", pRoot->data[j]);
	printf("\n");
	for (int i = 0; i <= pRoot->CurrentSize; ++i)
		TravelBTreeNode(pRoot->pChild[i]);
}
bool NoAppear(BTreeNode*pRoot, int InitNum)
{
	for (int i = 0; i < pRoot->CurrentSize; ++i)
		if (pRoot->data[i] == InitNum)
			return false;
	return true;
}
bool NoChild(BTreeNode*pRoot)
{
	for (int i = 0; i <= pRoot->CurrentSize; ++i)
		if (pRoot->pChild[i] != NULL)
			return false;
	return true;
}
bool NoFull(BTreeNode*pRoot)
{
	if (pRoot->CurrentSize < N)
		return true;
	return false;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值