#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define KeyType int
#define Record string
const int m = 3;
using namespace std;
typedef struct BTNode {
int keynum;
KeyType key[m + 1];
struct BTNode* parent;
struct BTNode* ptr[m + 1];
Record* recptr[m + 1];
BTNode() {
keynum = 0;
parent = NULL;
for (int i = 0; i < m + 1; i++)
{
ptr[i] = NULL;
}
}
}BTNode, * BTree;
BTree T = NULL;
typedef struct {
BTree pt;
int i;
int tag;
}result;
int Search(BTree p, int k) {
int i = 1;
while (i <= p->keynum && k > p->key[i]) i++;
return i;
}
void SearchBTree(BTree t, int k, result& r) {
int i = 0, found = 0;
BTree p = t, q = NULL;
while (p != NULL && 0 == found) {
i = Search(p, k);
if (i <= p->keynum && p->key[i] == k) found = 1;
else { q = p; p = p->ptr[i - 1]; }
}
if (1 == found) {
r = { p,i,1 };
}
else {
r = { q,i,0 };
}
}
void split(BTree& q, int s, BTree& ap) {
int i, j, n = q->keynum;
ap = (BTNode*)malloc(sizeof(BTNode));
ap->ptr[0] = q->ptr[s];
for (i = s + 1, j = 1; i <= n; i++, j++) {
ap->key[j] = q->key[i];
ap->ptr[j] = q->ptr[i];
}
ap->keynum = n - s;
ap->parent = q->parent;
for (i = 0; i <= n - s; i++)
if (ap->ptr[i] != NULL) ap->ptr[i]->parent = ap;
q->keynum = s - 1;
}
void newRoot(BTree& t, BTree p, int x, BTree ap) {
t = (BTNode*)malloc(sizeof(BTNode));
t->keynum = 1; t->ptr[0] = p; t->ptr[1] = ap; t->key[1] = x;
if (p != NULL) p->parent = t;
if (ap != NULL) ap->parent = t;
t->parent = NULL;
}
void Insert(BTree& q, int i, int x, BTree ap) {
int j, n = q->keynum;
for (j = n; j >= i; j--) {
q->key[j + 1] = q->key[j];
q->ptr[j + 1] = q->ptr[j];
}
q->key[i] = x; q->ptr[i] = ap;
if (ap != NULL) ap->parent = q;
q->keynum++;
}
void InsertBTree(BTree& t, int k, BTree q, int i) {
int x, s, finished = 0, needNewRoot = 0;
BTree ap;
if (NULL == q) newRoot(t, NULL, k, NULL);
else {
x = k; ap = NULL;
while (0 == needNewRoot && 0 == finished) {
Insert(q, i, x, ap);
if (q->keynum < m) finished = 1;
else {
s = (m + 1) / 2; split(q, s, ap); x = q->key[s];
if (q->parent != NULL) {
q = q->parent; i = Search(q, x);
}
else needNewRoot = 1;
}
}
if (1 == needNewRoot)
newRoot(t, q, x, ap);
}
}
void Remove(BTree& p, int i)
{
int j, n = p->keynum;
for (j = i; j < n; j++) {
p->key[j] = p->key[j + 1];
p->ptr[j] = p->ptr[j + 1];
}
p->keynum--;
}
void Successor(BTree& p, int i) {
BTree child = p->ptr[i];
while (child->ptr[0] != NULL) child = child->ptr[0];
p->key[i] = child->key[1];
p = child;
}
void Restore(BTree& p, int i, BTree& T) {
int j;
BTree ap = p->parent;
if (ap == NULL)
{
T = p;
p = p->parent;
return;
}
BTree lc, rc, pr;
int finished = 0, r = 0;
while (!finished)
{
r = 0;
while (ap->ptr[r] != p) r++;
if (r == 0)
{
r++;
lc = NULL, rc = ap->ptr[r];
}
else if (r == ap->keynum)
{
rc = NULL; lc = ap->ptr[r - 1];
}
else
{
lc = ap->ptr[r - 1]; rc = ap->ptr[r + 1];
}
if (r > 0 && lc != NULL && (lc->keynum > (m - 1) / 2))
{
p->keynum++;
for (j = p->keynum; j > 1; j--)
{
p->key[j] = p->key[j - 1];
p->ptr[j] = p->ptr[j - 1];
}
p->key[1] = ap->key[r];
p->ptr[1] = p->ptr[0];
p->ptr[0] = lc->ptr[lc->keynum];
if (NULL != p->ptr[0])
{
p->ptr[0]->parent = p;
}
ap->key[r] = lc->key[lc->keynum];
lc->keynum--;
finished = 1;
break;
}
else if (ap->keynum > r && rc != NULL && (rc->keynum > (m - 1) / 2))
{
p->keynum++;
p->key[p->keynum] = ap->key[r];
p->ptr[p->keynum] = rc->ptr[0];
if (NULL != p->ptr[p->keynum])
p->ptr[p->keynum]->parent = p;
ap->key[r] = rc->key[1];
rc->ptr[0] = rc->ptr[1];
for (j = 1; j < rc->keynum; j++)
{
rc->key[j] = rc->key[j + 1];
rc->ptr[j] = rc->ptr[j + 1];
}
rc->keynum--;
finished = 1;
break;
}
r = 0;
while (ap->ptr[r] != p)
r++;
if (r > 0 && (ap->ptr[r - 1]->keynum <= (m - 1) / 2))
{
lc = ap->ptr[r - 1];
p->keynum++;
for (j = p->keynum; j > 1; j--)
{
p->key[j] = p->key[j - 1];
p->ptr[j] = p->ptr[j - 1];
}
p->key[1] = ap->key[r];
p->ptr[1] = p->ptr[0];
ap->ptr[r] = lc;
for (j = 1; j <= lc->keynum + p->keynum; j++)
{
lc->key[lc->keynum + j] = p->key[j];
lc->ptr[lc->keynum + j] = p->ptr[j];
}
if (p->ptr[0])
{
for (j = 1; j <= p->keynum; j++)
if (p->ptr[p->keynum + j]) p->ptr[p->keynum + j]->parent = lc;
}
lc->keynum = lc->keynum + p->keynum;
for (j = r; j < ap->keynum; j++)
{
ap->key[j] = ap->key[j + 1];
ap->ptr[j] = ap->ptr[j + 1];
}
ap->keynum--;
pr = p; free(pr);
pr = NULL;
p = lc;
}
else
{
rc = ap->ptr[r + 1];
if (r == 0)
r++;
p->keynum++;
p->key[p->keynum] = ap->key[r];
p->ptr[p->keynum] = rc->ptr[0];
rc->keynum = p->keynum + rc->keynum;
ap->ptr[r - 1] = rc;
for (j = 1; j <= (rc->keynum - p->keynum); j++)
{
rc->key[p->keynum + j] = rc->key[j];
rc->ptr[p->keynum + j] = rc->ptr[j];
}
for (j = 1; j <= p->keynum; j++)
{
rc->key[j] = p->key[j];
rc->ptr[j] = p->ptr[j];
}
rc->ptr[0] = p->ptr[0];
if (p->ptr[0])
{
for (j = 1; j <= p->keynum; j++)
if (p->ptr[p->keynum + j]) p->ptr[p->keynum + j]->parent = rc;
}
for (j = r; j < ap->keynum; j++)
{
ap->key[j] = ap->key[j + 1];
ap->ptr[j] = ap->ptr[j + 1];
}
ap->keynum--;
pr = p;
free(pr);
pr = NULL;
p = rc;
}
ap = ap->parent;
if (p->parent->keynum >= (m - 1) / 2 || (NULL == ap && p->parent->keynum > 0))
finished = 1;
else if (ap == NULL)
{
pr = T;
T = p;
free(pr);
pr = NULL;
finished = 1;
}
p = p->parent;
}
}
void DeleteBTree(BTree& p, int i, BTree& T) {
if (p->ptr[i] != NULL) {
Successor(p, i);
DeleteBTree(p, 1, T);
}
else {
Remove(p, i);
if (p->keynum < (m - 1) / 2)
Restore(p, i, T);
}
}
void show_Btree(BTree& p)
{
if (p == NULL) { puts("B tree does not exist"); return; }
bool have_child = false;
printf("[");
for (int i = 1; i <= p->keynum; i++)
{
if (i == 1);
else printf(" ");
printf("%d", p->key[i]);
}
printf("]");
for (int i = 0; i <= p->keynum; i++)
{
if (p->ptr[i] != NULL)
{
if (i == 0) printf("<");
else printf(",");
show_Btree(p->ptr[i]);
have_child = true;
}
}
if (have_child) printf(">");
}
void show_Btree2(BTree& p, int deep)
{
if (p == NULL) { return; }
int i;
for (i = 0; i < p->keynum; i++)
{
show_Btree2(p->ptr[i], deep + 1);
for (int i = 0; i < deep; i++)
{
printf("\t");
}
printf("%d\n", p->key[i + 1]);
}
show_Btree2(p->ptr[i], deep + 1);
}
void Destory(BTree& t)
{
int i = 0;
if (t != NULL)
{
while (i < t->keynum)
{
Destory(t->ptr[i]);
free(t->ptr[i]);
i++;
}
}
free(t);
t = NULL;
}
void creat_btree()
{
T = new BTNode;
T->keynum = 0;
puts("New success");
}
void insert_keytype()
{
puts("Enter an element to be inserted");
KeyType temp;
cin >> temp;
result p;
SearchBTree(T, temp, p);
if (p.tag == 0)
{
InsertBTree(T, temp, p.pt, p.i);
puts("Insert success"); show_Btree(T);
puts("");
}
else puts("The element is already in the B tree.");
}
void find_keytype()
{
puts("Enter an element to find");
KeyType temp;
cin >> temp;
result p;
SearchBTree(T, temp, p);
if (p.tag)
{
puts("Find success");
}
else puts("Lookup failure");
}
void delete_keytype()
{
puts("Enter an element to be deleted");
KeyType temp;
cin >> temp;
result p;
SearchBTree(T, temp, p);
if (p.tag)
{
DeleteBTree(p.pt, p.i, T);
puts("Delete success"); show_Btree(T);
puts("");
}
else puts("The element does not exist in the B tree.");
}
int main()
{
int order = 0;
while (order != 7)
{
puts("---------------------------------------------------------------------");
puts("Select menu");
puts("1:Creat a new 3-B-tree");
puts("2:Insert element");
puts("3:Find element");
puts("4:Delete element");
puts("5:Print B-tree");
puts("6:exit");
cin >> order;
switch (order)
{
case 1: {Destory(T); creat_btree(); break; }
case 2: {insert_keytype(); break; }
case 3: {find_keytype(); break; }
case 4: {delete_keytype(); break; }
case 5: {show_Btree(T); puts(""); break; }
case 6: {return 0; }
}
}
return 0;
}