B+树删除(仅考虑阶数m>=3的情形,注意叶节点合并时需要修改叶节点顺序链表的链接指针,下文并未提到)
删除仅在叶节点上进行,在叶节点上删除给定关键码后,如果叶节点为根节点则删除操作结束(此时删除后的B+树可能为空树).如果不为根节点且含有的关键码树>=ceil(m/2)[ceil表示向上取整]则删除操作结束,如果删除的是叶节点最右侧的关键码,还需用新的最右侧关键码沿叶节点至根节点的路径向上更新父节点指向叶节点,父节点的父节点-指向父节点-----的索引项,直到根节点的索引项被更新或被更新的索引项不是节点最右侧索引项为止。如果删除关键码的叶节点不为根节点且关键码数等于ceil(m/2)-1,那么如果叶节点有右兄弟节点,且右兄弟节点的关键码数大于等于ceil(m/2)+1,则把右兄弟节点最左侧关键码上移替代指向叶节点索引项中的关键码,并把最左侧关键码复制至叶节点最右侧,至此删除操作结束。如果右兄弟节点的关键码数等于ceil(m/2),则将被删叶节点完整拼接至右兄弟节点左侧,删除叶节点和指向它的索引项,然后若父节点为根或父节点不为根且关键码数大于等于ceil(m/2)则结束删除操作,否则回溯至父节点继续处理。
如果叶节点既无右兄弟节点也无左兄弟节点则删除父节点(根节点),并令根节点指针指向叶节点,然后删除操作结束
如果叶节点没有右兄弟节点,但有左兄弟节点,且左兄弟节点关键码数大于等于ceil(m/2)+1,则将父节点指向左兄弟节点的索引项中的关键码下移至叶节点最左侧,删除左兄弟节点最右侧关键码,然后用左兄弟节点新的最右侧关键码填补父节点指向它的索引项中关键码位置,随后同样的,若叶节点最右侧关键码小于父节点最右侧关键码则向上更新祖先节点索引项,然后删除操作结束。
如果叶节点没有右兄弟节点但有左兄弟节点,且左兄弟节点关键码数等于ceil(m/2)则将左兄弟节点完整拼接至叶节点左侧,然后删除左兄弟节点和父节点中指向它的索引项,随后若父节点为根节点或父节点不为根节点且关键码数大于等于ceil(m/2)则删除操作结束(注意若叶节点最右侧关键码小于父节点最右侧关键码则应向上更新祖先节点索引项),否则用叶节点最右侧关键码更新父节点最右侧关键码,然后回溯至父节点继续处理
现设删除操作中当前节点的关键码数为ceil(m/2)-1且不是叶节点。
那么如果它有右兄弟,且右兄弟关键码数大于等于ceil(m/2)+1则把右兄弟最左侧关键码上移取代父节点中指向当前节点的索引项中的关键码,并将该关键码复制至当前节点最右侧,此外还应将右兄弟最左侧指针移动至当前节点最右侧,然后删除操作结束
如果它有右兄弟,且右兄弟关键码数等于ceil(m/2),则当前节点拼接至右兄弟最左侧,删去当前节点和父节点中指向它的索引项,然后父节点为根节点或父节点不为根节点且关键码数大于等于ceil(m/2)则删除操作结束,否则回溯至父节点进一步处理。
若果它没有右兄弟也无左兄弟则删除父节点(根节点),并令根节点指针指向当前节点,然后删除操作结束
若果它没有右兄弟但有左兄弟,且左兄弟关键码数大于等于ceil(m/2)+1,则将父节点中指向左兄弟的索引项中的关键码下移至当前节点最左侧,删除左兄弟最右侧关键码并将左兄弟最右侧指针移至当前节点最左侧,最后用左兄弟新的最右侧关键码填补父节点中指向它的索引项中的关键码所在位置,删除操作结束(注意若当前节点最右侧关键码小于父节点最右侧关键码则应向上更新祖先节点索引项)
如果它没有右兄弟但有左兄弟,且左兄弟关键码数等于ceil(m/2),则将左兄弟完整拼接至当前节点左侧,然后删除左兄弟和父节点中指向它的索引项,随后若父节点为根节点或父节点不为根节点且关键码数大于等于ceil(m/2)则删除操作结束(注意若当前节点最右侧关键码小于父节点最右侧关键码则应向上更新祖先节点索引项),否则用叶节点最右侧关键码更新父节点最右侧关键码,然后回溯至父节点继续处理
B+树插入(仅考虑阶数m>=3的情形,注意叶节点分裂时需要修改叶节点顺序链表的链接指针,下文并未提到)
在空树中插入,直接新建根节点并填入关键码并令root和head指针指向根节点即可
若在非空树中插入那么通过搜索在叶节点中找到插入位置直接插入,若插入后叶节点关键码数小于等于m则插入结束,否则叶节点从中间分裂为长度分别为floor((m+1)/2)和ceil((m+1)/2)的两部分,长度为ceil((m+1)/2)的部分是分裂后的原叶节点。如果原叶节点没有父节点则创建新根节点,左右两关键码为两分裂部分的最大关键码,左右两指针分别指向两分裂部分,令根节点指针指向新根节点,插入结束,否则将最大关键码较小的分裂部分的指针及其最大关键码构成的二元组插入至原叶节点父节点中最大关键码较大的分裂部分对应的二元组的左侧,父节点关键码指针数加一。如果插入二元组后父节点关键码数小于等于m,则插入结束,否则以父节点为当前节点回溯至父节点
现设插入过程中当前节点有m+1个关键码且不为叶节点,则和上述类似将当前节点分裂为长度分别为floor((m+1)/2)和ceil((m+1)/2)的两部分,长度为ceil((m+1)/2)的部分是分裂后的原当前节点,如果原当前节点没有父节点则创建新根节点,左右两关键码为两分裂部分的最大关键码,左右两指针分别指向两分裂部分,令根节点指针指向新根节点,插入结束,否则将最大关键码较小的分裂部分的指针及其最大关键码构成的二元组插入至原当前节点父节点中最大关键码较大的分裂部分对应的二元组的左侧,父节点关键码指针数加一。如果插入二元组后父节点关键码数小于等于m,则插入结束,否则以父节点为当前节点回溯至父节点
C++代码实现(如有错误欢迎指出)
1 #include "stdafx.h" 2 #include <iostream> 3 #include <map> 4 #include <stack> 5 #include <vector> 6 #include <set> 7 using namespace std; 8 9 const int M = 4; //B+树阶数 10 template <typename T> 11 struct BPlusTreeNode 12 { 13 union 14 { 15 pair<set<T>, BPlusTreeNode<T> *> *keyandptr; //叶节点指针域和数据域 16 map<T, BPlusTreeNode<T> *> * keyptrmap; //分支节点索引项集合 17 }; 18 enum flag {leaf, branch} NodeFlag; //节点标志叶节点or分支节点 19 BPlusTreeNode(flag N); 20 ~BPlusTreeNode(); 21 }; 22 23 template <typename T> 24 BPlusTreeNode<T>::BPlusTreeNode(flag N) 25 { 26 NodeFlag = N; 27 if (NodeFlag == leaf) 28 { 29 keyandptr = new pair<set<T>, BPlusTreeNode<T> *>(set<T>(), nullptr); 30 } 31 else 32 { 33 keyptrmap = new map<T, BPlusTreeNode<T> *>(); 34 } 35 } 36 37 template <typename T> 38 BPlusTreeNode<T>::~BPlusTreeNode() 39 { 40 if (NodeFlag == leaf) 41 { 42 delete keyandptr; 43 } 44 else 45 { 46 delete keyptrmap; 47 } 48 } 49 50 template <typename T> 51 void updatemax(stack<pair<BPlusTreeNode<T> *, typename map<T, BPlusTreeNode<T> *>::iterator>> &stackforback, T key) //向上更新父节点索引项关键码 52 { 53 while (stackforback.empty() == false) 54 { 55 typename map<T, BPlusTreeNode<T> *>::iterator temp = stackforback.top().second; 56 if (temp == stackforback.top().first->keyptrmap->end()) 57 --temp; 58 BPlusTreeNode<T> *ptr = temp->second; 59 stackforback.top().first->keyptrmap->erase(temp); 60 temp = stackforback.top().first->keyptrmap->insert(make_pair(key, ptr)).first; 61 ++temp; 62 if (temp != stackforback.top().first->keyptrmap->end()) 63 { 64 break; 65 } 66 stackforback.pop(); 67 } 68 } 69 70 template <typename T> 71 pair<BPlusTreeNode<T> *, BPlusTreeNode<T> *> BPlusInsert(BPlusTreeNode<T> *root, BPlusTreeNode<T> *head, T key) //B+树插入函数 72 { 73 if (root == nullptr) 74 { 75 root = new BPlusTreeNode<T>(BPlusTreeNode<T>::flag::leaf); 76 head = root; 77 root->keyandptr->first.insert(key); 78 return {root, head}; 79 } 80 else 81 { 82 BPlusTreeNode<T> * current = root; 83 stack<pair<BPlusTreeNode<T> *, map<T, BPlusTreeNode<T> *>::iterator>> stackforback; 84 85 if (current->NodeFlag != BPlusTreeNode<T>::flag::leaf) 86 { 87 while (current->NodeFlag != BPlusTreeNode<T>::flag::leaf) 88 { 89 BPlusTreeNode<T> *p = nullptr; 90 typename map<T, BPlusTreeNode<T> *>::iterator scankey = current->keyptrmap->begin(); 91 while (key > (*scankey).first) 92 { 93 ++scankey; 94 if (scankey == current->keyptrmap->end()) 95 { 96 stackforback.push(make_pair(current, scankey)); 97 --scankey; // 98 p = scankey->second; 99 ++scankey; 100 while (p->NodeFlag != BPlusTreeNode<T>::flag::leaf) 101 { 102 typename map<T, BPlusTreeNode<T> *>::iterator temp = p->keyptrmap->end(); 103 stackforback.push(make_pair(p, temp)); 104 --temp; 105 p = temp->second; 106 } 107 108 break; 109 } 110 } 111 112 if (scankey == current->keyptrmap->end()) 113 { 114 current = p; 115 break; 116 } 117 118 stackforback.push(make_pair(current, scankey)); 119 current = (*scankey).second; 120 } 121 } 122 123 { 124 typename set<T>::iterator temp; 125 if ((temp = current->keyandptr->first.find(key)) == current->keyandptr->first.end()) 126 { 127 temp = current->keyandptr->first.end(); 128 --temp; 129 current->keyandptr->first.insert(key); 130 if (current->keyandptr->first.size() <= M) 131 { 132 ++temp; 133 if (current != root && temp != current->keyandptr->first.end()) 134 { 135 updatemax(stackforback, *temp); 136 } 137 return { root, head }; 138 } 139 else 140 { 141 BPlusTreeNode<T> *ptr = new BPlusTreeNode<T>(BPlusTreeNode<T>::flag::leaf); 142 temp = current->keyandptr->first.begin(); 143 while (ptr->keyandptr->first.size() < (M + 1) / 2) 144 { 145 ptr->keyandptr->first.insert(*temp); 146 temp = current->keyandptr->first.erase(temp); 147 } 148 ptr->keyandptr->second = current; 149 150 if (stackforback.empty() == true) 151 { 152 head = ptr; 153 root = new BPlusTreeNode<T>(BPlusTreeNode<T>::flag::branch); 154 temp = ptr->keyandptr->first.end(); 155 --temp; 156 root->keyptrmap->insert(make_pair(*temp, ptr)); 157 temp = current->keyandptr->first.end(); 158 --temp; 159 root->keyptrmap->insert(make_pair(*temp, current)); 160 return { root, head }; 161 } 162 else 163 { 164 if (current != head) //优化 165 { 166 BPlusTreeNode<T> *p = head; 167 for (; p->keyandptr->second != current; p = p->keyandptr->second); 168 p->keyandptr->second = ptr; 169 } 170 else 171 { 172 head = ptr; 173 } 174 175 temp = ptr->keyandptr->first.end(); 176 --temp; 177 stackforback.top().first->keyptrmap->insert(make_pair(*temp, ptr)); 178 179 if (stackforback.top().first->keyptrmap->size() <= M) 180 { 181 if (stackforback.top().second == stackforback.top().first->keyptrmap->end()) 182 { 183 temp = current->keyandptr->first.end(); 184 --temp; 185 updatemax(stackforback, *temp); 186 } 187 return { root, head }; 188 } 189 else 190 { 191 if (stackforback.top().second == stackforback.top().first->keyptrmap->end()) 192 { 193 temp = current->keyandptr->first.end(); 194 --temp; 195 typename map<T, BPlusTreeNode<T> *>::iterator it = stackforback.top().second; 196 --it; 197 ptr = it->second; 198 stackforback.top().first->keyptrmap->erase(it); 199 stackforback.top().first->keyptrmap->insert(make_pair(*temp, ptr)); 200 } 201 current = stackforback.top().first; 202 stackforback.pop(); 203 204 while (true) 205 { 206 BPlusTreeNode<T> *ptr = new BPlusTreeNode<T>(BPlusTreeNode<T>::flag::branch); 207 typename map<T, BPlusTreeNode<T> *>::iterator temp = current->keyptrmap->begin(); 208 209 while (ptr->keyptrmap->size() < (M + 1) / 2) 210 { 211 ptr->keyptrmap->insert(*temp); 212 temp = current->keyptrmap->erase(temp); 213 } 214 215 if (stackforback.empty() == true) 216 { 217 root = new BPlusTreeNode<T>(BPlusTreeNode<T>::flag::branch); 218 temp = ptr->keyptrmap->end(); 219 --temp; 220 root->keyptrmap->insert(make_pair((*temp).first, ptr)); 221 temp = current->keyptrmap->end(); 222 --temp; 223 root->keyptrmap->insert(make_pair((*temp).first, current)); 224 return { root, head }; 225 } 226 else 227 { 228 temp = ptr->keyptrmap->end(); 229 --temp; 230 stackforback.top().first->keyptrmap->insert(make_pair((*temp).first, ptr)); 231 232 if (stackforback.top().first->keyptrmap->size() <= M) 233 { 234 if (stackforback.top().second == stackforback.top().first->keyptrmap->end()) 235 { 236 temp = current->keyptrmap->end(); 237 --temp; 238 updatemax(stackforback, (*temp).first); 239 } 240 return {root, head}; 241 } 242 else 243 { 244 if (stackforback.top().second == stackforback.top().first->keyptrmap->end()) 245 { 246 temp = current->keyptrmap->end(); 247 --temp; 248 typename map<T, BPlusTreeNode<T> *>::iterator it = stackforback.top().second; 249 --it; 250 ptr = it->second; 251 stackforback.top().first->keyptrmap->erase(it); 252 stackforback.top().first->keyptrmap->insert(make_pair((*temp).first, ptr)); 253 } 254 current = stackforback.top().first; 255 stackforback.pop(); 256 } 257 } 258 } 259 } 260 } 261 } 262 } 263 else 264 { 265 cout << "关键码" << key << "已存在,无法插入" << endl; 266 return { root, head }; 267 } 268 } 269 } 270 } 271 272 template <typename T> 273 pair<BPlusTreeNode<T> *, BPlusTreeNode<T> *> BPlusDelete(BPlusTreeNode<T> *root, BPlusTreeNode<T> *head, T key) //B+树删除函数,root根节点指针,head叶节点顺序链头节点指针 274 { 275 BPlusTreeNode<T> * current = root; 276 stack<pair<BPlusTreeNode<T> *, map<T, BPlusTreeNode<T> *>::iterator>> stackforback; 277 278 if (current->NodeFlag != BPlusTreeNode<T>::flag::leaf) 279 { 280 while (current->NodeFlag != BPlusTreeNode<T>::flag::leaf) 281 { 282 typename map<T, BPlusTreeNode<T> *>::iterator scankey = current->keyptrmap->begin(); 283 while (key > (*scankey).first) 284 { 285 ++scankey; 286 if (scankey == current->keyptrmap->end()) 287 { 288 cout << "关键码不存在删除失败" << endl; 289 return { root, head }; 290 } 291 } 292 293 stackforback.push(make_pair(current, scankey)); 294 current = (*scankey).second; 295 } 296 } 297 298 { 299 typename set<T>::iterator temp; 300 if ((temp = current->keyandptr->first.find(key)) == current->keyandptr->first.end()) 301 { 302 cout << "关键码不存在删除失败" << endl; 303 return { root, head }; 304 } 305 else 306 { 307 current->keyandptr->first.erase(temp); 308 } 309 } 310 311 if (stackforback.empty() == true) 312 { 313 if (current->keyandptr->first.empty() == true) 314 { 315 delete current; 316 return { nullptr, nullptr }; 317 } 318 else 319 { 320 return { current, current }; 321 } 322 } 323 else 324 { 325 if (current->keyandptr->first.size() >= (M + 1) / 2) 326 { 327 typename set<T>::iterator temp = current->keyandptr->first.end(); 328 --temp; 329 if (*temp < key) 330 { 331 updatemax(stackforback, *temp); 332 } 333 return {root, head}; 334 } 335 else 336 { 337 typename map<T, BPlusTreeNode<T> *>::iterator temp = stackforback.top().second; 338 ++temp; 339 if (temp != stackforback.top().first->keyptrmap->end()) 340 { 341 if (temp->second->keyandptr->first.size() >= (M + 1) / 2 + 1) 342 { 343 current->keyandptr->first.insert(*(temp->second->keyandptr->first.begin())); 344 stackforback.top().first->keyptrmap->erase(stackforback.top().second); 345 stackforback.top().first->keyptrmap->insert(make_pair(*(temp->second->keyandptr->first.begin()), current)); 346 temp->second->keyandptr->first.erase(temp->second->keyandptr->first.begin()); 347 return {root, head}; 348 } 349 else 350 { 351 temp->second->keyandptr->first.insert(current->keyandptr->first.begin(), current->keyandptr->first.end()); 352 if (current != head) //优化 353 { 354 BPlusTreeNode<T> *p = head; 355 for (; p->keyandptr->second != current; p = p->keyandptr->second); 356 p->keyandptr->second = current->keyandptr->second; 357 } 358 else 359 { 360 head = current->keyandptr->second; 361 } 362 delete current; 363 stackforback.top().first->keyptrmap->erase(stackforback.top().second); 364 if (stackforback.top().first == root || stackforback.top().first->keyptrmap->size() >= (M + 1) / 2) 365 { 366 return {root, head}; 367 } 368 else 369 { 370 current = stackforback.top().first; 371 stackforback.pop(); 372 } 373 } 374 } 375 else 376 { 377 --temp; 378 if (temp != stackforback.top().first->keyptrmap->begin()) 379 { 380 --temp; 381 if (temp->second->keyandptr->first.size() >= (M + 1) / 2 + 1) 382 { 383 current->keyandptr->first.insert(temp->first); 384 BPlusTreeNode<T> *temp1 = temp->second; 385 stackforback.top().first->keyptrmap->erase(temp); 386 typename set<T>::iterator it = temp1->keyandptr->first.end(); 387 --it; 388 it = temp1->keyandptr->first.erase(it); 389 --it; 390 stackforback.top().first->keyptrmap->insert(make_pair(*it, temp1)); 391 392 typename set<T>::iterator temp = current->keyandptr->first.end(); 393 --temp; 394 if (*temp < key) 395 { 396 updatemax(stackforback, *temp); 397 } 398 return { root, head }; 399 } 400 else 401 { 402 current->keyandptr->first.insert(temp->second->keyandptr->first.begin(), temp->second->keyandptr->first.end()); 403 if (temp->second != head) //优化 404 { 405 BPlusTreeNode<T> *p = head; 406 for (; p->keyandptr->second != temp->second; p = p->keyandptr->second); 407 p->keyandptr->second = temp->second->keyandptr->second; 408 } 409 else 410 { 411 head = temp->second->keyandptr->second; 412 } 413 delete temp->second; 414 stackforback.top().first->keyptrmap->erase(temp); 415 416 typename set<T>::iterator temp = current->keyandptr->first.end(); 417 --temp; 418 if (stackforback.top().first == root || stackforback.top().first->keyptrmap->size() >= (M + 1) / 2) 419 { 420 if (*temp < key) 421 { 422 updatemax(stackforback, *temp); 423 } 424 return { root, head }; 425 } 426 else 427 { 428 if (*temp < key) 429 { 430 typename map<T, BPlusTreeNode<T> *>::iterator temp1 = stackforback.top().second; 431 BPlusTreeNode<T> *ptr = temp1->second; 432 stackforback.top().first->keyptrmap->erase(temp1); 433 stackforback.top().first->keyptrmap->insert(make_pair(*temp, ptr)); 434 } 435 current = stackforback.top().first; 436 stackforback.pop(); 437 } 438 } 439 } 440 else 441 { 442 delete stackforback.top().first; 443 return { current, head }; 444 } 445 } 446 } 447 } 448 449 while (true) 450 { 451 typename map<T, BPlusTreeNode<T> *>::iterator temp = stackforback.top().second; 452 ++temp; 453 if (temp != stackforback.top().first->keyptrmap->end()) 454 { 455 if (temp->second->keyptrmap->size() >= (M + 1) / 2 + 1) 456 { 457 current->keyptrmap->insert(*(temp->second->keyptrmap->begin())); 458 stackforback.top().first->keyptrmap->erase(stackforback.top().second); 459 stackforback.top().first->keyptrmap->insert(make_pair(temp->second->keyptrmap->begin()->first, current)); 460 temp->second->keyptrmap->erase(temp->second->keyptrmap->begin()); 461 return { root, head }; 462 } 463 else 464 { 465 temp->second->keyptrmap->insert(current->keyptrmap->begin(), current->keyptrmap->end()); 466 delete current; 467 stackforback.top().first->keyptrmap->erase(stackforback.top().second); 468 if (stackforback.top().first == root || stackforback.top().first->keyptrmap->size() >= (M + 1) / 2) 469 { 470 return { root, head }; 471 } 472 else 473 { 474 current = stackforback.top().first; 475 stackforback.pop(); 476 } 477 } 478 } 479 else 480 { 481 --temp; 482 if (temp != stackforback.top().first->keyptrmap->begin()) 483 { 484 --temp; 485 if (temp->second->keyptrmap->size() >= (M + 1) / 2 + 1) 486 { 487 BPlusTreeNode<T> *temp1 = temp->second; 488 stackforback.top().first->keyptrmap->erase(temp); 489 typename map<T, BPlusTreeNode<T> *>::iterator it = temp1->keyptrmap->end(); 490 --it; 491 current->keyptrmap->insert(*it); 492 it = temp1->keyptrmap->erase(it); 493 --it; 494 stackforback.top().first->keyptrmap->insert(make_pair((*it).first, temp1)); 495 496 typename map<T, BPlusTreeNode<T> *>::iterator temp = current->keyptrmap->end(); 497 --temp; 498 if ((*temp).first < key) 499 { 500 updatemax(stackforback, (*temp).first); 501 } 502 return { root, head }; 503 } 504 else 505 { 506 current->keyptrmap->insert(temp->second->keyptrmap->begin(), temp->second->keyptrmap->end()); 507 delete temp->second; 508 stackforback.top().first->keyptrmap->erase(temp); 509 510 typename map<T, BPlusTreeNode<T> *>::iterator temp = current->keyptrmap->end(); 511 --temp; 512 if (stackforback.top().first == root || stackforback.top().first->keyptrmap->size() >= (M + 1) / 2) 513 { 514 if ((*temp).first < key) 515 { 516 updatemax(stackforback, (*temp).first); 517 } 518 return { root, head }; 519 } 520 else 521 { 522 if ((*temp).first < key) 523 { 524 typename map<T, BPlusTreeNode<T> *>::iterator temp1 = stackforback.top().second; 525 BPlusTreeNode<T> *ptr = temp1->second; 526 stackforback.top().first->keyptrmap->erase(temp1); 527 stackforback.top().first->keyptrmap->insert(make_pair((*temp).first, ptr)); 528 } 529 current = stackforback.top().first; 530 stackforback.pop(); 531 } 532 } 533 } 534 else 535 { 536 delete stackforback.top().first; 537 return { current, head }; 538 } 539 } 540 } 541 } 542 543 int main() 544 { 545 vector<int> seq{ 2, 7, 5, 19, 10, 18, 16, 12, 11, 15, 13, 14, 21, 29, 25, 20, 22, 28, 23, 26 }; 546 BPlusTreeNode<int> *root = nullptr; 547 BPlusTreeNode<int> *head = nullptr; 548 for (vector<int>::const_iterator p = seq.cbegin(); p != seq.cend(); ++p) 549 { 550 cout << "插入节点" << *p << endl; 551 pair<BPlusTreeNode<int> *, BPlusTreeNode<int> * > temp = BPlusInsert(root, head, *p); 552 root = temp.first; 553 head = temp.second; 554 cout << endl; 555 } 556 557 for (vector<int>::const_iterator p = seq.cbegin(); p != seq.cend(); ++p) 558 { 559 cout << "删除节点" << *p << endl; 560 pair<BPlusTreeNode<int> *, BPlusTreeNode<int> * > temp = BPlusDelete(root, head, *p); 561 root = temp.first; 562 head = temp.second; 563 if (root == nullptr) 564 cout << "NULL"; 565 cout << endl; 566 } 567 return 0; 568 }
运行结果: