#include<iostream>
using namespace std;
static const int MMM = 5; //B树阶数
//static const int key_max = MMM + 1; //key[0]不作用途, key[m]用于插入分裂时使用
#define DEFAULT 333
struct node
{
int *key; //关键码数组 [m/2-1]到[m-1],若m/2-1小于1,则关键码至少为1
//T *data; //暂时不想考虑,其实data数组只要紧跟key数组就行
node *parent;
node **child;
int key_num; //当前关键码个数
node() :key_num(0), parent(NULL), child(NULL)
{
key = new int[MMM + 1];
key[0] = 0;
child = new node*[MMM + 1];
parent = NULL;
for (int i = 0; i < MMM + 1; i++)
{
child[i] = NULL;
}
}
~node() //用类对象表示节点时必须写,结构体应该可以不用谢
{
for (int i = 0; i < MMM + 1; i++)
{
delete child[i];
child[i] = NULL;
}
delete key;
delete child;
child = NULL;
}
};
class B_tree
{
private:
node *b_root;
public:
B_tree() :b_root(new node) {}
~B_tree()
{
Destory(b_root);
delete b_root->key;
b_root->key = NULL;
b_root->parent = NULL;
for (int i = 0; i < b_root->key_num; i++)
{
delete b_root->child[i];
b_root->child[i] = NULL;
}
b_root = NULL;
};
void Insert(const int k); //往B树中插入节点 只要考虑最大子树个数,删除是才要考虑【m/2】这个最小子树个数
node* Search(node *root, const int k); //在B树中寻找关键码值为k的关键码,并返回所在的节点
node* Split(node* &root, const int index); //插入节点后向上分裂 返回值类型任意
node* Root(); //获取根节点
void Level_order(); //层序遍历B树
void Adjust(node *root); //调整B树
bool Remove(const int k); //删除内部节点,用后继节点节点代替,即复制删除
void Destory(node *root); //销毁B树
};
inline node* B_tree::Root()
{
return b_root;
}
node* B_tree::Search(node *root, const int k)
{
if (root->key_num == 0)
{
cout << “B树为空,查找失败!” << endl;
return NULL;
}
while (root->child[0] != 0)
{
for (int i = root->key_num; i >= 0; i–)
{
if (root->key[i] == k)
{
cout << “关键码值 ” << k << ” 是B树的关键码!” << endl;
return root;
}
if (root->key[i] < k)
{
root = root->child[i];
break;
}
}
}
for (int i = 1; i <= root->key_num; i++)
{
if (root->key[i] == k)
{
cout << “关键码值 ” << k << ” 是B树的关键码!” << endl;
return root;
}
}
cout << “关键码值 ” << k << ” 不是B树的关键码!” << endl;
return NULL;
}
void B_tree::Insert(const int k) //往B树中插入节点 只要考虑最大子树个数,删除是才要考虑【m/2】这个最小子树个数
{
node *root = b_root;
for (int m = 1; m <= root->key_num; m++)
{
cout << “[” << root->key[m] << “]”;
}
cout << endl;
if (root->child[0] == NULL && root->key_num == 0)
{
root->key_num++;
root->key[1] = k;
root->parent = NULL;
return;
}
int i, j;
while (root->child[0] != NULL)
{
for (i = root->key_num; i >= 0; i–)
{
if (root->key[i] == k)
{
cout << “关键码值 ” << k << ” 已经是B树的关键码!” << endl;
return;
}
if (root->key[i] < k)
{
root = root->child[i];
break;
}
}
}
for (i = root->key_num; i >= 0; i–)
{
if (root->key[i] == k)
{
cout << “B树中已经有 ” << k << ” 这个关键码” << endl;
return;
}
if (root->key[i] < k)
{
for (j = root->key_num; j > i; j–)
{
root->key[j + 1] = root->key[j];
}
root->key[i + 1] = k;
root->key_num++;
break;
}
}
while (root->key_num == MMM)
{
Split(root, (1 + MMM) / 2);
}
}
node* B_tree::Split(node* &root, int index) //root节点是待分裂节点
{
int i, j;
int k = root->key[index];
node *other = new node; //root节点分裂后的另一半
for (i = index + 1; i <= root->key_num; i++)
{
other->key[i – index] = root->key[i];
other->key_num++;
}
if (root->child[0] != NULL) //分裂节点为内部节点
{
for (i = index; i <= root->key_num; i++)
{
other->child[i – index] = root->child[i]; //分裂内部节点时,孩子比关键码要多一个
root->child[i]->parent = other; //这个是重中之重, 移动分裂孩子节点其父节点必须一并修改
//delete root->child[i]; //删除后,空间释放,会出问题,指针置空就行 类可以,结构体删除即释放
root->child[i] = NULL;
}
}
root->key_num = index – 1;
if (root->parent == NULL)
{
node *r = new node; //新根节点,树的高度会增加
r->key_num++;
r->key[1] = k;
r->child[0] = root;
r->child[1] = other;
r->parent = NULL;
other->parent = r;
root->parent = r;
b_root = r;
return b_root;
}
else
{
node *p = root->parent;
for (i = p->key_num; i >= 0; i–)
{
if (p->key[i] < k)
{
break;
}
}
for (j = p->key_num; j > i; j–)
{
p->key[j + 1] = p->key[j];
p->child[j + 1] = p->child[j];
}
p->key_num++;
p->key[i + 1] = k;
p->child[i + 1] = other;
//p->child[i] = root; //注意下就行
other->parent = p;
root = p;
return root;
}
}
void B_tree::Level_order() //层序遍历B树
{
if (b_root == NULL)
{
cout << “B树为空,层序遍历失败!” << endl;
return;
}
node **qu = new node*[DEFAULT];
int front = 0;
int rear = 0;
qu[front] = qu[rear++] = b_root;
int max = DEFAULT; //假设循环空间足够大,要不然还得判断是不是装满了
int counter = 0;
cout << “B树的层序遍历为:{“;
while (front != rear)
{
node *p = qu[front];
front = (front + 1) % max;
if (counter = 1)
{
cout << “[“;
for (int i = 1; i <= p->key_num; i++)
{
cout << ” ” << p->key[i] << ” “;
}
cout << “]”;
}
//cout << endl;
if (p->child[0] != NULL)
{
for (int j = 0; j <= p->key_num; j++)
{
qu[rear] = p->child[j];
rear = (rear + 1) % max;
}
}
counter++;
}
cout << “}”;
}
bool B_tree::Remove(const int k)
{
node *root = b_root;
root = Search(root, k);
if (root == NULL)
{
cout << “B树中不存在关键码值为 ” << k << ” 的关键码!” << endl;
return false;
}
int i, index;
for (i = 1; i <= root->key_num; i++) //确定k所在的节点
{
if (root->key[i] == k)
{
index = i; //k为其所在节点第i个元素
break;
}
}
if (root->child[0] == NULL) //被删除的关键码在叶节点上
{
for (i = index; i < root->key_num; i++) //在节点中删除k,并移动关键码数组
{
root->key[i] = root->key[i + 1];
}
root->key_num–;
if (root->parent == NULL) //只有根节点
{
if (root->key_num == 0) //根节点没有关键码,B树为空
{
root = NULL;
}
return true;
}
if (root->key_num >= (MMM – 1) / 2) //删除k后的节点关键码的个数比最少大,直接返回
{
return true;
}
else
{
Adjust(root); //调整B树
}
}
if (root->child[0] != NULL) //如果k在内部节点中,先把其与其后继最小的交换,然后相当于删除叶节点
{
node *curr = root->child[index];
while (curr->child[0] != NULL) //直到找到k节点后继中的最小值,然后复制删除
{
curr = curr->child[0];
}
root->key[index] = curr->key[1]; //复制删除
curr->key[1] = k;
for (i = 1; i < curr->key_num; i++)
{
curr->key[i] = curr->key[i + 1];
}
curr->key_num–;
if (curr->key_num >= (MMM – 1) / 2)
{
return true;
}
else
{
Adjust(curr);
}
}
return true;
}
void B_tree::Adjust(node *root)
{
if (root->parent == NULL)
{
return;
}
int i, index;
node *p = root->parent;
for (i = 0; i <= p->key_num; i++) //确定root节点在父节点孩子节点指针数组中的位置
{
if (p->child[i] == root)
{
index = i;
break;
}
}
cout << index << endl;
if (index == 0) //防止越界,不写这个判定条件跟右边借总会出问题,非得这样坑我
{
if (p->child[index + 1] != NULL && p->child[index + 1]->key_num > (MMM – 1) / 2) //右兄弟
{
node *right = p->child[index + 1];
root->key_num++;
root->key[root->key_num] = p->key[index + 1];
p->key[index + 1] = right->key[1];
for (i = 1; i < right->key_num; i++)
{
right->key[i] = right->key[i + 1];
}
if (root->child[0] != NULL) //root不为叶子节点
{
root->child[root->key_num] = right->child[0];
right->child[0]->parent = root;
for (i = 0; i < right->key_num; i++)
{
right->child[i] = right->child[i + 1];
}
right->child[right->key_num] = NULL;
}
right->key_num–;
return;
}
if (p->child[index + 1] != NULL && p->child[index + 1]->key_num == (MMM – 1) / 2)
{
node *right = p->child[index + 1];
root->key_num++;
root->key[root->key_num] = p->key[index + 1];
if (root->child[0] != NULL)
{
int mmm = root->key_num;
for (i = 0; i <= right->key_num; i++)
{
root->child[mmm++] = right->child[i];
right->child[i]->parent = root;
}
}
for (i = 1; i <= right->key_num; i++)
{
root->key_num++;
root->key[root->key_num] = right->key[i];
}
for (i = index + 1; i < p->key_num; i++)
{
p->child[i] = p->child[i + 1];
p->key[i] = p->key[i + 1];
}
p->child[p->key_num] = NULL;
p->key_num–;
delete right;
right = NULL;
if (p == b_root && p->key_num == 0)
{
p = NULL;
b_root = root;
root->parent = NULL;
return;
}
if (p->key_num < (MMM – 1) / 2)
{
Adjust(p);
}
}
}
if (index > 0 && index <= p->key_num)
{
if (p->child[index – 1] != NULL && p->child[index – 1]->key_num > (MMM – 1) / 2) //左兄弟
{
node *left = p->child[index – 1];
for (i = root->key_num; i >= 1; i–)
{
root->key[i + 1] = root->key[i];
}
root->key[1] = p->key[index];
p->key[index] = left->key[left->key_num];
if (root->child[0] != NULL)
{
for (i = root->key_num; i >= 0; i–)
{
root->child[i + 1] = root->child[i];
}
root->child[0] = left->child[left->key_num];
left->child[left->key_num]->parent = root;
left->child[left->key_num] = NULL;
}
root->key_num++;
left->key_num–;
return;
}
if (p->child[index – 1] != NULL && p->child[index – 1]->key_num == (MMM – 1) / 2)
{
node *left = p->child[index – 1];
left->key_num++;
left->key[left->key_num] = p->key[index];
if (root->child[0] != NULL)
{
int mmm = left->key_num;
for (i = 0; i <= root->key_num; i++)
{
left->child[mmm++] = root->child[i];
root->child[i]->parent = left;
}
}
for (i = 1; i <= root->key_num; i++)
{
left->key_num++;
left->key[left->key_num] = root->key[i];
}
for (i = index; i < p->key_num; i++)
{
p->child[i] = p->child[i + 1];
p->key[i] = p->key[i + 1];
}
p->child[p->key_num] = NULL;
p->key_num–;
root = NULL;
if (p == b_root && b_root->key_num == 0)
{
p = NULL;
b_root = left;
left->parent = NULL;
return;
}
if (p->key_num < (MMM – 1) / 2)
{
Adjust(p);
}
}
}
}
void B_tree::Destory(node *root)
{
if (root->child[0] == NULL && root->key_num != 0)
{
delete root->key;
root->key = NULL;
root->parent = NULL;
for (int i = 0; i < root->key_num; i++)
{
delete root->child[i];
root->child[i] = NULL;
}
delete root;
root = NULL;
return;
}
if (root->child[0] != NULL)
{
for (int i = 0; i <= root->key_num; i++)
{
Destory(root->child[i]);
}
}
}
void main()
{
B_tree tree;
node *root = new node;
int arr[22] = { 39,22,97,41,53,13,21,40,30,27,33,36,35,34,24,29,26,23,17,28,31,32 };
for (int i = 0; i < 22; i++)
{
tree.Insert(arr[i]);
}
root = tree.Root();
tree.Search(root, 35);
tree.Level_order();
cout << endl;
tree.Remove(13);
tree.Level_order();
cout << endl;
tree.Remove(27);
tree.Level_order();
cout << endl;
tree.Remove(32);
tree.Level_order();
cout << endl;
tree.Remove(40);
tree.Level_order();
cout << endl;
tree.Remove(17);
tree.Level_order();
cout << endl;
tree.Remove(34);
tree.Level_order();
cout << endl;
tree.Remove(22);
tree.Level_order();
cout << endl;
tree.Remove(23);
tree.Level_order();
cout << endl;
tree.Remove(21);
tree.Level_order();
cout << endl;
tree.Remove(24);
tree.Level_order();
cout << endl;
tree.Remove(36);
tree.Level_order();
cout << endl;
tree.Remove(39);
tree.Level_order();
cout << endl;
tree.Remove(31);
tree.Level_order();
cout << endl;
tree.Remove(33);
tree.Level_order();
cout << endl;
tree.Remove(28);
tree.Level_order();
cout << endl;
tree.Remove(97);
tree.Level_order();
cout << endl;
tree.Remove(53);
tree.Level_order();
cout << endl;
tree.Remove(41);
tree.Level_order();
cout << endl;
tree.Remove(26);
tree.Remove(29);
tree.Remove(30);
tree.Remove(35);
tree.Level_order();
cout << endl;
//tree.Destory(tree.Root());
tree.Level_order();
}