B树

  1 #include "B_Tree.h"
  2 #include <iostream>
  3 
  4 
  5 B_Tree::B_Tree(int hie)
  6 {
  7     root_ = new B_Node(hie);
  8     hierarchy_ = hie;
  9 }
 10 
 11 
 12 B_Tree::~B_Tree()
 13 {
 14 }
 15 
 16 
 17 void B_Tree::Insert(int val)
 18 {
 19     //找到叶子节点
 20     auto leaf = SearchLeaf(root_, val);
 21     //插入到叶子节点
 22     InsertNode(leaf, val);
 23 }
 24 
 25 
 26 void B_Tree::Print(B_Node*tree)
 27 {
 28     for (int i = 0; i < tree->key_num; i++)
 29     {
 30         std::cout << tree->key_list[i]->key << " \n";
 31     }
 32     std::cout << "---\n";
 33 
 34     for (int i = 0; i < tree->child_num; i++)
 35     {
 36         Print(tree->child_list[i]);
 37     }
 38 
 39 }
 40 
 41 B_Node* B_Tree::SearchLeaf(B_Node*tree,int val)
 42 {
 43     //叶子节点
 44     if (tree->child_num == 0)
 45     {
 46         return tree;
 47     }
 48     else
 49     {
 50         for (int i = 0; i <= tree->key_num - 1; i++)
 51         {
 52             if (val < tree->key_list[i]->key)
 53             {
 54                 return SearchLeaf((tree->child_list[i]),val);
 55             }
 56         }
 57 
 58         //最后一个child指针继续寻找
 59         return  SearchLeaf((tree->child_list[tree->child_num-1]), val);
 60     }
 61 }
 62 
 63 
 64 /*
 65 1.取当前节点key队列的中间节点mid
 66 2.分裂成左右两边
 67 3.mid插入起父节点
 68 4.返回父节点
 69 */
 70 B_Node * B_Tree::SplitNode(B_Node*tree)
 71 {
 72     B_Node*parent = tree->parent;
 73     //如果当前节点为根节点,新建一个新的根节点,当前节点分裂成两个节点
 74     if (parent == nullptr)
 75     {
 76         //创建新的根节点
 77         parent = new B_Node(hierarchy_);
 78         root_ = parent;
 79         parent->child_list[0] = tree;
 80         tree->parent = parent;
 81         parent->child_num++;
 82     }
 83 
 84     auto mid_key = tree->key_list[tree->key_num / 2];
 85 
 86     //插入mid key到父节点
 87     InsertValToKeyList(parent, mid_key->key);
 88 
 89 
 90     //创建tree的兄弟节点bro
 91     //tree分裂出一半给bro
 92     B_Node *bro = new B_Node(hierarchy_);
 93     //mid kid移到父节点
 94     tree->key_list[tree->key_num / 2] = nullptr;
 95     tree->key_num--;
 96     int ptr =1+ tree->key_num / 2;
 97     int child_num = tree->child_num;
 98     for (int i = ptr; i < child_num; i++)
 99     {
100         auto adsf = tree->child_list[i];
101         bro->child_list[i - ptr] = tree->child_list[i];
102         bro->child_list[i - ptr]->parent = parent;
103         tree->child_list[i] = nullptr;
104         tree->child_num--;
105         bro->child_num++;
106     }
107     int key_num = tree->key_num;
108     for (int i = ptr; i <= key_num; i++)
109     {
110         bro->key_list[i - ptr] = tree->key_list[i];
111         tree->key_list[i] = nullptr;
112         bro->key_num++;
113         tree->key_num--;
114     }
115     bro->parent = parent;
116 
117     for (int i = 0; i < parent->child_num; i++)
118     {
119         if (tree == parent->child_list[i])
120         {
121             B_Node *pre_node = parent->child_list[i + 1];
122             parent->child_list[i + 1] = bro;
123             int child_num = parent->child_num;
124             parent->child_num++;
125             for (int j = i+2; j <= child_num; j++)
126             {
127                 parent->child_list[j] = pre_node;
128                 pre_node = parent->child_list[j+1];
129             }
130             break;
131         }
132     }    
133 
134     return parent;
135 }
136 
137 void B_Tree::InsertNode(B_Node*tree, int val)
138 {
139     //叶子结点未满 直接插入
140     if (tree->key_num < hierarchy_ - 1)
141     {
142         return InsertValToKeyList(tree, val);
143     }
144     else{
145         
146         //先将叶子节点插满
147         InsertValToKeyList(tree, val);
148 
149         //分裂叶子节点,并且把mid node上移到父节点
150         auto parent = SplitNode(tree);
151         //Print(root_);
152         while (parent->child_num > hierarchy_)
153         {
154             parent = SplitNode(parent);
155         }
156 
157     }
158 
159 }
160 
161 
162 void B_Tree::InsertValToKeyList(B_Node *node, int val)
163 {
164     B_KEY *tmp_node = new B_KEY();
165     if (node->key_num == 0)
166     {
167         tmp_node->key = val;
168         node->key_list[0] = tmp_node;
169         node->key_num++;
170         return;
171     }
172 
173     for (int i = 0; i < node->key_num; i++)
174     {
175         if (val > node->key_list[i]->key)
176         {
177             continue;
178         }
179         else
180         {
181             int pre_key = node->key_list[i]->key;
182             node->key_list[i]->key = val;
183             for (int j = i+1; j < node->key_num + 1; j++)
184             {
185                 int tmp = pre_key;
186                 if (j != node->key_num)
187                     pre_key = node->key_list[j]->key;
188                 else
189                     node->key_list[j] = tmp_node;
190                 node->key_list[j]->key = tmp;
191             }
192             node->key_num++;
193             return;
194         }
195     }
196     node->key_list[node->key_num] = tmp_node;
197     node->key_list[node->key_num]->key = val;
198     node->key_num++;
199     return;
200 }

 

m阶B树性质:

  • 每个节点最少有ceil(m/2)-1个key,最多有m-1个key,最多有m个child
  • 根节点最少可以有2个child
  • 叶子结点都在同一层

B树的插入:

  • 先找到要插入的叶子结点
  • 如果叶子结点key小于m-1,直接插入,完成操作,否则下一步
  • 插入key后,叶子结点找到(m-1)/2位置的key,提取出来,插入到其父节点,key的位置为X。叶子结点从中间分裂成两个节点A、B,X左侧child指向A,X右侧child指向B
  • 递归父节点,直到分裂到根节点结束
posted @ 2019-03-11 11:08  仙7道  阅读(141)  评论(0)    收藏  举报