B-树(B-Tree)的C++演示代码

 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;
}

    原文作者:B树
    原文地址: https://blog.csdn.net/Vaan/article/details/1524697
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞