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
- 递归父节点,直到分裂到根节点结束
浙公网安备 33010602011771号