/* 前言: 好多天前准备记录下自己的坎坷修仙的点滴,以后希望能留下【珍贵的回忆】,萌新的日常代码,大佬互喷*/
代码写的比较繁琐,多多见谅,萌新每天都在努力改变自己
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;
}