#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <math.h>
#define OK 1
#define ERROR 0
#define FALSE 0
#define TRUE 1
#define OVERFLOW -2
#define LH 1
#define RH -1
#define EH 0
#define GRADE 4
typedef int Status;
typedef int KeyType;
typedef struct
{
KeyType key;
}ElemType;
typedef struct
{
ElemType* elem;
int length;
}SSTable;
typedef ElemType TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
typedef struct BSTNode
{
TElemType data;
int bf;
struct BSTNode* lchild, * rchild;
}BSTNode, * BSTree;
typedef struct BTNode
{
int keynum;
struct BTNode* parent;
KeyType key[GRADE + 1];
struct BTNode* ptr[GRADE + 2];
ElemType* recptr[GRADE + 1];
}BTNode, * BTree;
typedef struct
{
BTNode* ptr;
int i;
int tag;
}Result;
//查找表元素输入,关键字赋值以及比较
void InputTableElem(ElemType* e)
{
printf("请输入关键字信息\n");
scanf("%d", &(e->key));
}
void KeyWordAssign(KeyType* destination, KeyType source)
{
(*destination) = source;
}
void KeyWordPrint(KeyType key)
{
printf("%d\n", key);
}
void TableElemAssign(ElemType* destination, ElemType source)
{
(*destination).key = source.key;
}
void TableElemPrint(ElemType e)
{
printf("%d\n", e.key);
}
Status EQ(KeyType key1, KeyType key2)
{
if (key1 == key2)
return TRUE;
else
return FALSE;
}
Status LT(KeyType key1, KeyType key2)
{
if (key1 < key2)
return TRUE;
else
return FALSE;
}
Status LE(KeyType key1, KeyType key2)
{
if (key1 <= key2)
return TRUE;
else
return FALSE;
}
Status MT(KeyType key1, KeyType key2)
{
if (key1 > key2)
return TRUE;
else
return FALSE;
}
Status ME(KeyType key1, KeyType key2)
{
if (key1 >= key2)
return TRUE;
else
return FALSE;
}
//静态查找表
Status CreatSSTable(SSTable* T, int n)
{
T->length = n;
T->elem = (ElemType*)malloc(sizeof(ElemType) * (n + 1));
if (!T->elem) exit(OVERFLOW);
for (int i = 1; i <= T->length; i++)
{
printf("请输入第%d个表项信息:\n", i);
InputTableElem(&(T->elem[i]));
}
return OK;
}
int Search_Seq(SSTable ST, KeyType key) //Sequence Search
{
KeyWordAssign(&(ST.elem[0].key), key);
int i = ST.length;
while (!EQ(ST.elem[i].key, key))
i--;
return i;
}
int Search_Bin(SSTable ST, KeyType key) //Binary Search
{
int low = 1, high = ST.length;
int mid = (low + high) / 2;
while (low <= high)
{
if (EQ(ST.elem[mid].key, key))
return mid;
if (MT(ST.elem[mid].key, key))
high = mid - 1;
else
low = mid + 1;
}
return 0;
}
void SecondOptimal(BiTree* T, SSTable S, int* sw, int low, int high)
{
int i = low;
int w = sw[high] + sw[low - 1];
int min = abs(sw[high] - sw[low]);
for (int j = low + 1; j <= high; j++)
{
if (abs(w - sw[j - 1] - sw[j]) < min)
{
i = j;
min = abs(w - sw[i] - sw[i - 1]);
}
}
(*T) = (BiTree)malloc(sizeof(BiTNode));
if (!(*T)) exit(OVERFLOW);
KeyWordAssign(&((*T)->data.key), S.elem[i].key);
if (i == low)
(*T)->lchild = NULL;
else
SecondOptimal(&((*T)->lchild), S, sw, low, i - 1);
if (i == high)
(*T)->rchild = NULL;
else
SecondOptimal(&((*T)->rchild), S, sw, i + 1, high);
}
//队列函数
typedef BTNode* QElemType;
typedef struct QNode
{
QElemType data;
struct QNode* next;
}QNode, * QueuePtr;
typedef struct
{
QueuePtr head, tail;
}LinkQueue;
Status InitQueue(LinkQueue* Q)
{
Q->head = (QueuePtr)malloc(sizeof(QNode));
if (!Q->head) exit(OVERFLOW);
Q->tail = Q->head;
Q->head->next = NULL;
return OK;
}
Status EnQueue(LinkQueue* Q, QElemType e)
{
QNode* p;
p = (QNode*)malloc(sizeof(QNode));
if (!p) exit(OVERFLOW);
p->data = e;
Q->tail->next = p;
Q->tail = p;
Q->tail->next = NULL;
return OK;
}
Status DeQueue(LinkQueue* Q, QElemType* e)
{
if (Q->head == Q->tail)
return ERROR;
QNode* p = Q->head->next;
(*e) = p->data;
Q->head->next = p->next;
if (p == Q->tail)
Q->tail = Q->head;
free(p);
return OK;
}
Status QueueEmpty(LinkQueue Q)
{
if (Q.head == Q.tail)
return TRUE;
else
return FALSE;
}
//B-树与B+树
void PrintBTree(BTree T)
{
if (!T)
printf("B-树为空\n");
else
{
printf("B树层序输出为:\n");
LinkQueue Q;
InitQueue(&Q);
EnQueue(&Q, T);
QElemType p;
while (!QueueEmpty(Q))
{
DeQueue(&Q, &p);
int i = 0;
while (i < p->keynum)
{
//KeyWordPrint(p->key[i]);
TableElemPrint(*(p->recptr[i]));
if (p->ptr[i])
EnQueue(&Q, p->ptr[i]);
i++;
}
if (p->ptr[i])
EnQueue(&Q, p->ptr[i]);
}
}
}
int Search(BTree T, KeyType key) //找B-树的一个节点中找记录,若找到,为找到记录的位置,未找到则为插入位置
{ //若树不存在,则位置为0
int i = 0;
while (T && i < T->keynum && LT(T->key[i], key))
i++;
return i;
}
Status SearchBTree(BTree T, KeyType key, Result* res)
{
BTNode* p = T, * q = NULL;
int found = FALSE;
int i = 0;
while (p && (found == FALSE))
{
i = Search(p, key);
if (i < p->keynum && EQ(p->key[i], key))
found = TRUE;
else
{
q = p;
p = p->ptr[i];
}
}
if (found)
{
res->tag = TRUE;
res->i = i;
res->ptr = p;
}
else
{
res->tag = FALSE;
res->i = i;
res->ptr = q;
}
return OK;
}
Status CreatBTNode(BTree* T, ElemType e)
{
(*T) = (BTree)malloc(sizeof(BTNode));
if (!(*T)) exit(OVERFLOW);
(*T)->keynum = 1;
KeyWordAssign(&((*T)->key[0]), e.key);
(*T)->recptr[0] = (ElemType*)malloc(sizeof(ElemType));
if (!(*T)->recptr[0]) exit(OVERFLOW);
TableElemAssign((*T)->recptr[0], e);
return OK;
}
int Split(BTree T1, BTree T2)
{
int split = ceil(GRADE / 2);
T1->keynum = split - 1;
T2->keynum = GRADE - split;
split--;
for (int i = split + 1; i < GRADE; i++)
{
KeyWordAssign(&(T2->key[i - split - 1]), T1->key[i]);
T2->ptr[i - split - 1] = T1->ptr[i];
T2->recptr[i - split - 1] = T1->recptr[i];
}
T2->ptr[GRADE - split - 1] = T1->ptr[GRADE];
return split;
}
Status InsertBTree(BTree* ROOT, BTree* T, int pos, ElemType e, BTree T1, BTree T2)
{
if (!(*T))
{
CreatBTNode(ROOT, e);
(*ROOT)->parent = NULL;
(*ROOT)->ptr[pos] = T1;
(*ROOT)->ptr[pos + 1] = T2;
(*T) = (*ROOT);
}
else
{
if ((*T)->keynum < GRADE)
{
int i = (*T)->keynum - 1;
while (i >= pos)
{
(*T)->ptr[i + 2] = (*T)->ptr[i + 1];
KeyWordAssign(&((*T)->key[i + 1]), (*T)->key[i]);
(*T)->recptr[i + 1] = (*T)->recptr[i];
i--;
}
KeyWordAssign(&((*T)->key[pos]), e.key);
(*T)->recptr[pos] = (ElemType*)malloc(sizeof(ElemType));
if (!(*T)->recptr[pos]) exit(OVERFLOW);
TableElemAssign((*T)->recptr[pos], e);
(*T)->ptr[pos] = T1;
(*T)->ptr[pos + 1] = T2;
(*T)->keynum++;
}
if ((*T)->keynum == GRADE)
{
BTNode* new;
new = (BTNode*)malloc(sizeof(BTNode));
if (!new) exit(OVERFLOW);
int splitpos = Split((*T), new);
int i = Search((*T)->parent, (*T)->key[splitpos]);
InsertBTree(ROOT, &((*T)->parent), i, *((*T)->recptr[splitpos]), (*T), new);
new->parent = (*T)->parent;
(*T) = (*T)->parent;
}
}
return OK;
}
Status Delete_BT(BTree* ROOT, BTree* T, int pos)
{
int min = ceil(GRADE / 2) - 1;
for (int i = pos; i <= (*T)->keynum - 2; i++)
{
KeyWordAssign(&((*T)->key[i]), (*T)->key[i + 1]);
(*T)->recptr[i] = (*T)->recptr[i + 1];
}
(*T)->keynum--;
if ((*T) == (*ROOT))
{
if ((*T)->keynum == 0)
(*ROOT) = (*T)->ptr[0];
}
else
{
if ((*T)->keynum < min)
{
BTNode* parent = (*T)->parent;
BTNode* lsibling = NULL, * rsibling = NULL, * helpsibling = NULL;
int childpos = Search(parent, (*T)->key[pos]);
if (childpos - 1 > 0)
lsibling = parent->ptr[childpos - 1];
if (childpos + 1 <= parent->keynum)
rsibling = parent->ptr[childpos + 1];
int tag = 0;
if (lsibling)
{
tag = 1;
helpsibling = lsibling;
}
if (rsibling)
{
tag = 2;
helpsibling = rsibling;
}
if (lsibling && lsibling->keynum > min)
{
tag = 3;
helpsibling = lsibling;
}
if (rsibling && rsibling->keynum > min)
{
tag = 4;
helpsibling = rsibling;
}
int last;
switch (tag)
{
case 1:
last = helpsibling->keynum;
KeyWordAssign(&(helpsibling->key[last]), parent->key[childpos - 1]);
helpsibling->recptr[last] = (ElemType*)malloc(sizeof(ElemType));
if (!helpsibling->recptr[last]) exit(OVERFLOW);
helpsibling->recptr[last] = parent->recptr[childpos - 1];
helpsibling->keynum++;
last++;
for (int i = 0; i < (*T)->keynum; i++)
{
KeyWordAssign(&(helpsibling->key[last + i]), (*T)->key[i]);
helpsibling->recptr[last + i] = (ElemType*)malloc(sizeof(ElemType));
if (!helpsibling->recptr[last + i]) exit(OVERFLOW);
helpsibling->recptr[last + i] = (*T)->recptr[i];
helpsibling->keynum++;
helpsibling->ptr[last + i] = (*T)->ptr[i];
}
helpsibling->ptr[helpsibling->keynum] = (*T)->ptr[(*T)->keynum];
for (int i = parent->keynum - 1; i >= childpos; i--)
parent->ptr[i] = parent->ptr[i + 1];
Delete_BT(ROOT, &parent, childpos - 1);
break;
case 2:
last = (*T)->keynum;
KeyWordAssign(&((*T)->key[last]), parent->key[childpos]);
(*T)->recptr[last] = (ElemType*)malloc(sizeof(ElemType));
if (!(*T)->recptr[last]) exit(OVERFLOW);
(*T)->recptr[last] = parent->recptr[childpos];
(*T)->keynum++;
last++;
for (int i = 0; i < helpsibling->keynum; i++)
{
KeyWordAssign(&((*T)->key[last + i]), helpsibling->key[i]);
(*T)->recptr[last + i] = (ElemType*)malloc(sizeof(ElemType));
if (!(*T)->recptr[last + i]) exit(OVERFLOW);
(*T)->recptr[last + i] = helpsibling->recptr[i];
(*T)->keynum++;
(*T)->ptr[last + i] = helpsibling->ptr[i];
}
(*T)->ptr[(*T)->keynum] = helpsibling->ptr[helpsibling->keynum];
for (int i = parent->keynum - 1; i >= childpos + 1; i--)
parent->ptr[i] = parent->ptr[i + 1];
Delete_BT(ROOT, &parent, childpos);
break;
case 3:
(*T)->ptr[(*T)->keynum + 1] = (*T)->ptr[(*T)->keynum];
for (int i = (*T)->keynum - 1; i > 0; i--)
{
KeyWordAssign(&((*T)->key[i + 1]), (*T)->key[i]);
(*T)->recptr[i + 1] = (*T)->recptr[i];
(*T)->ptr[i + 1] = (*T)->ptr[i];
}
KeyWordAssign(&((*T)->key[0]), parent->key[childpos - 1]);
(*T)->recptr[0] = parent->recptr[childpos - 1];
(*T)->keynum++;
last = helpsibling->keynum;
KeyWordAssign(&(parent->key[childpos - 1]), helpsibling->key[last - 1]);
parent->recptr[childpos - 1] = helpsibling->recptr[last - 1];
(*T)->ptr[0] = helpsibling->ptr[last];
Delete_BT(ROOT, &helpsibling, last - 1);
break;
case 4:
last = (*T)->keynum;
KeyWordAssign(&((*T)->key[last]), parent->key[childpos]);
(*T)->recptr[last] = parent->recptr[childpos];
(*T)->keynum++;
KeyWordAssign(&(parent->key[childpos]), helpsibling->key[0]);
parent->recptr[childpos] = helpsibling->recptr[0];
(*T)->ptr[(*T)->keynum] = helpsibling->ptr[0];
for (int i = 0; i < helpsibling->keynum; i++)
helpsibling->ptr[i] = helpsibling->ptr[i + 1];
Delete_BT(ROOT, &helpsibling, 0);
break;
default:
return ERROR;
}
}
}
}
Status DeleteBTree(BTree* ROOT, BTree* T, int pos)
{
if ((*T)->ptr[pos] != NULL)
{
Result res;
SearchBTree((*T)->ptr[pos], (*T)->key[pos], &res);
KeyWordAssign(&((*T)->key[pos]), res.ptr->key[res.i - 1]);
(*T)->recptr[pos] = res.ptr->recptr[res.i - 1];
Delete_BT(ROOT, &(res.ptr), res.i - 1);
}
else
Delete_BT(ROOT, T, pos);
return OK;
}
主函数:
//B-树主函数
int main()
{
BTree T = NULL, ROOT = NULL;
Result res;
int count = 10;
ElemType e;
while (count)
{
InputTableElem(&e);
SearchBTree(ROOT, e.key, &res);
T = res.ptr;
InsertBTree(&ROOT, &T, res.i, e, NULL, NULL);
count--;
}
PrintBTree(ROOT);
count = 10;
printf("--------------------------------\n\n");
while (count && ROOT)
{
printf("需要输入关键字以删除节点\n");
InputTableElem(&e);
SearchBTree(ROOT, e.key, &res);
T = res.ptr;
DeleteBTree(&ROOT, &T, res.i);
PrintBTree(ROOT);
printf("--------------------------------\n\n");
count--;
}
return 0;
}
输入:(P245所示B树构造,然后将B树节点一一删去)
45
24
53
90
3
37
50
61
70
100
输出:
删除45:
以此类推以验证程序正确性