B-树(B-Tree)的C++演示代码
按照算法导论中伪代码转化,其中删除过程算法导论没有给出伪代码,所以对删除相关函数做了说明。另外B-Tree本来是用于硬盘的,但为了简便只阐明B-Tree的基本流程,没有加入硬盘扇区的直接读写操作,全部在内存中进行。
1.头文件(B-Tree.h)
#ifndef BTREE__JOHN__DMRC
#define BTREE__JOHN__DMRC
/*************************** Class BTreeNode ***************************/
template <typename T>
class BTreeNode{
public:
BTreeNode(int, bool);
~BTreeNode();
// Varies
int t;
int len;
bool leaf;
T* key;
BTreeNode<T>** child;
};
/**************************** Class BTree ******************************/
template <typename T>
class BTree{
public:
BTree(int);
~BTree();
bool BTree_Search(T);
void BTree_Insert(T);
bool BTree_Delete(T);
// debug start
void print_root();
// debug end
private:
bool btree_search(BTreeNode<T>*, T);
void delete_tree(BTreeNode<T>*);
void btree_split_child(BTreeNode<T>*, int, BTreeNode<T>*);
void btree_insert_nonfull(BTreeNode<T>*, T);
void btree_merge_child(BTreeNode<T>*, int);
void btree_rotate_child(BTreeNode<T>*, int, bool);
bool btree_delete_nonfew(BTreeNode<T>*, T);
BTreeNode<T>* root;
int t;
};
#endif
2 cpp文件(B-Tree.cpp)
#include “B-Tree.h”
/*************************** Class BTreeNode ***************************/
template <typename T>
BTreeNode<T>::BTreeNode(int a, bool b){
this ->t = a;
this ->len = 0;
this ->leaf = b;
this ->key = new int[2 * a – 1];
this ->child = new BTreeNode*[2 * a];
}
template <typename T>
BTreeNode<T>::~BTreeNode(){
delete [] this ->key;
delete [] this ->child;
}
/**************************** Class BTree ******************************/
// C & D
template <typename T>
BTree<T>::BTree(int a){
this ->t = a;
this ->root = new BTreeNode<T>(a, true);
}
template <typename T>
BTree<T>::~BTree(){
this ->delete_tree(this ->root);
}
template <typename T>
void BTree<T>::delete_tree(BTreeNode<T>* p){
if(!p ->leaf){
for(int i = 0; i < p ->len + 1; i ++)
this ->delete_tree(p ->child[i]);
}
delete p;
}
// Search
template <typename T>
bool BTree<T>::BTree_Search(T k){
return this ->btree_search(this ->root, k);
}
template <typename T>
bool BTree<T>::btree_search(BTreeNode<T>* x, T k){
int i;
if(x ->leaf){
for(i = 0; i < x ->len; i ++)
if(x ->key[i] == k)
return true;
return false;
}
else{
for(i = 0; i < x ->len; i ++)
if(x ->key[i] > k)
break;
return this ->btree_search(x ->child[i], k);
}
}
// Insert series
template <typename T>
void BTree<T>::BTree_Insert(T k){
BTreeNode<T>* r = this ->root;
if(this ->root ->len == 2 * this ->t – 1){
BTreeNode<T>* s = new BTreeNode<T>(this ->t, false);
this ->root = s;
s ->child[0] = r;
this ->btree_split_child(s, 0, r);
this ->btree_insert_nonfull(s, k);
}
else
this ->btree_insert_nonfull(r, k);
}
template <typename T>
void BTree<T>::btree_split_child(BTreeNode<T>* x, int i, BTreeNode<T>* y){
BTreeNode<T>* z = new BTreeNode<T>(this ->t, y ->leaf);
int j;
z ->len = this ->t – 1;
for(j = 0; j < t -1 ; j ++)
z ->key[j] = y ->key[this ->t + j];
if(!y ->leaf){
for(j = 0; j < t; j ++)
z ->child[j] = y ->child[this -> t + j];
}
y ->len = this ->t – 1;
for(j = x ->len; j > i + 1; j –)
x ->child[j + 1] = x ->child[j];
x ->child[i + 1] = z;
for(j = x ->len – 1; j > i; j –)
x ->key[j + 1] = x ->key[j];
x ->key[i] = y ->key[this ->t – 1];
x ->len ++;
}
template <typename T>
void BTree<T>::btree_insert_nonfull(BTreeNode<T>* x, T k){
int i = x ->len;
if(x ->leaf){
while(i > 0 && k < x ->key[i – 1]){
x ->key[i] = x ->key[i – 1];
i –;
}
x ->key[i] = k;
x ->len ++;
}
else{
while(i > 0 && k < x ->key[i – 1])
i –;
if(x ->child[i] ->len == 2 * this ->t – 1){
this ->btree_split_child(x, i , x ->child[i]);
if(k > x ->key[i])
i ++;
}
this ->btree_insert_nonfull(x ->child[i], k);
}
}
// Delete series
template <typename T>
bool BTree<T>::BTree_Delete(T k){
BTreeNode<T>* p = this ->root;
if(this ->root ->len == 1 && !this ->root ->leaf
&& this ->root ->child[0] ->len == this ->t – 1
&& this ->root ->child[1] ->len == this ->t – 1){
this ->btree_merge_child(this ->root, 0);
this ->root = this ->root ->child[0];
delete p;
return this ->btree_delete_nonfew(this ->root, k);
}
return this ->btree_delete_nonfew(p, k);
}
/*********** FUNCTION: btree_merge_child() ***************
** x : point to the parent
** i : merge child(i) and child(i+1) of x into child(i)
**********************************************************/
template <typename T>
void BTree<T>::btree_merge_child(BTreeNode<T>* x, int i){
int j;
BTreeNode<T>* y = x ->child[i];
BTreeNode<T>* z = x ->child[i + 1];
// assert delete
if(y ->len != this ->t – 1 || z ->len != this ->t – 1){
printf(“Error delete!/n”);
exit(0);
}
y ->len = this ->t * 2 – 1;
for(j = 0; j < this ->t – 1; j ++)
y ->key[this ->t + j] = z ->key[j];
y ->key[this ->t – 1] = x ->key[i];
if(!z ->leaf){
for(j = 0; j < this ->t; j ++)
y ->child[this ->t + j] = z ->child[j];
}
for(j = i; j < x ->len – 1; j ++)
x ->key[j] = x ->key[j + 1];
for(j = i + 1; j < x ->len; j ++)
x ->child[j] = x ->child[j + 1];
x ->len –;
}
/********** FUNCTION: btree_rotate_child() ***************
** x : point to the parent
** i : rotate from the i th child of x
** rol_right : true if rotate to right, false if left
**********************************************************/
template <typename T>
void BTree<T>::btree_rotate_child(BTreeNode<T>* x, int i, bool rol_right){
BTreeNode<T>* y;
BTreeNode<T>* z;
int j;
if(rol_right){
y = x ->child[i];
z = x ->child[i + 1];
// change right child
for(j = z ->len; j > 0; j –)
z ->key[j] = z ->key[j – 1];
for(j = z ->len + 1; j > 0; j –)
z ->child[j] = z ->child[j – 1];
z ->key[0] = x ->key[i];
z ->child[0] = y ->child[y ->len];
z ->len ++;
// change parant
x ->key[i] = y ->key[y ->len – 1];
// change left child
y ->len –;
}
else{
y = x ->child[i – 1];
z = x ->child[i];
// change left child
y ->key[y ->len] = x ->key[i – 1];
y ->child[y ->len + 1] = z ->child[0];
y ->len ++;
// change parent
x ->key[i – 1] = z ->key[0];
// change right child
for(j = 0; j < z ->len – 1; j ++)
z ->key[j] = z ->key[j + 1];
for(j = 0; j < z ->len; j ++)
z ->child[j] = z ->child[j + 1];
z ->len –;
}
}
template <typename T>
bool BTree<T>::btree_delete_nonfew(BTreeNode<T>* x, T k){
int i;
if(x ->leaf){
for(i = 0; i < x ->len; i ++){
if(x ->key[i] == k){
while(i < x ->len – 1){
//x ->key[i] = x ->key[i ++];
x ->key[i] = x ->key[i + 1];
i ++;
}
x ->len –;
return true;
}
}
return false;
}
else{
for(i = 0; i < x ->len; i ++){
if(x ->key[i] > k)
break;
}
if(x ->child[i] ->len > this ->t – 1)
return this ->btree_delete_nonfew(x ->child[i], k);
else{
if(i == 0){
if(x ->child[i + 1] ->len > this ->t – 1)
this ->btree_rotate_child(x, i + 1, false);
else
this ->btree_merge_child(x, i);
return this ->btree_delete_nonfew(x ->child[i], k);
}
else if(i == x ->len){
if(x ->child[i – 1] ->len > this ->t – 1)
this ->btree_rotate_child(x, i – 1, true);
else
this ->btree_merge_child(x, i – 1);
return this ->btree_delete_nonfew(x ->child[i – 1], k);
}
else{
if(x ->child[i – 1] ->len > this ->t – 1)
this ->btree_rotate_child(x, i – 1, true);
else if(x ->child[i + 1] ->len > this -> t – 1)
this ->btree_rotate_child(x, i + 1, false);
else
this ->btree_merge_child(x, i);
return this ->btree_delete_nonfew(x ->child[i], k);
}
}
}
}
// print_root( for debug )
template <typename T>
void BTree<T>::print_root(){
int i;
printf(“Root Data : “);
for(i = 0; i < this ->root ->len; i ++)
printf(“%d “, this ->root ->key[i]);
if(!this ->root ->leaf){
printf(” Child Length : “);
for(i = 0; i < this ->root ->len + 1; i ++)
printf(“%d “, this ->root ->child[i] ->len);
putchar(‘/n’);
}
else
printf(“/n”);
}
3 演示文件(main.cpp)
#include <iostream>
#include “B-Tree.h”
#include “B-Tree.cpp”
using namespace std;
int main(void){
BTree<int> t(2);
int i;
cout << “Insert 1 – 9 to B-Tree :” << endl;
for(i = 1; i < 10; i ++){
t.BTree_Insert(i);
printf(“[%d] “, i);
t.print_root();
}
putchar(‘/n’);
cout << “Delete 1 – 5 from B-Tree :” << endl;
for(i = 1; i < 6; i ++){
if(t.BTree_Delete(i)){
printf(“[%d] “, i);
t.print_root();
}
if(t.BTree_Search(3))
printf(“3 is in B-Tree now./n/n”);
else
printf(“3 is not in B-Tree now./n/n”);
}
putchar(‘/n’);
cout << “Insert 10 – 15 to B-Tree :” << endl;
for(i = 10; i < 16; i ++){
t.BTree_Insert(i);
printf(“[%d] “, i);
t.print_root();
}
putchar(‘/n’);
cout << “Delete all from B-Tree :” << endl;
for(i = 6; i < 16; i ++){
if(t.BTree_Delete(i)){
printf(“[%d] “, i);
t.print_root();
}
}
putchar(‘/n’);
return 0;
}