-
定義
一顆m階B+樹滿足以下幾個條件:
1.除根節點外的節點的關鍵字個數最大為m-1,最小為m/2
2.除葉節點外的每個節點的孩子節點的數目為該節點關鍵字個數加一,這些孩子節點的的關鍵字的范圍與父節點關鍵字的大小對應(這個看圖才看的清楚)
3.葉子節點存放着所有的關鍵字,葉子節點間按關鍵字的大小用指針相互連接。內部節點以葉子節點的關鍵字的最小值作為索引
-
B+樹的優勢
B+樹相較於B樹最大的優勢在於數據全部都存在於葉子節點,葉子節點間以指針相互連接,這樣在進行按照索引的范圍查找的時候就只需要遍歷前后指針就可以完成,而B樹要一個一個索引去進行查找,效率差別很大。
B+樹相較於hash的優勢在於B+樹不用一次將數據全部加載到內存,而是先確定要查詢索引的地址,將對應的地址的索引加載到內存。而hash需要將全部的數據一次性加載到內存才能完成查找。
-
B+樹代碼實現
首先定義一個節點類
1 import java.util.List; 2 3 /*節點類*/ 4 public class Node { 5 6 //節點的子節點 7 private List<Node> nodes; 8 //節點的鍵值對 9 private List<KeyAndValue> keyAndValue; 10 //節點的后節點 11 private Node nextNode; 12 //節點的前節點 13 private Node previousNode; 14 //節點的父節點 15 private Node parantNode; 16 17 public Node( List<Node> nodes, List<KeyAndValue> keyAndValue, Node nextNode,Node previousNode, Node parantNode) { 18 this.nodes = nodes; 19 this.keyAndValue = keyAndValue; 20 this.nextNode = nextNode; 21 this.parantNode = parantNode; 22 this.previousNode = previousNode; 23 } 24 25 boolean isLeaf() { 26 return nodes==null; 27 } 28 29 boolean isHead() { 30 return previousNode == null; 31 } 32 33 boolean isTail() { 34 return nextNode == null; 35 } 36 37 boolean isRoot() { 38 return parantNode == null; 39 } 40 41 42 List<Node> getNodes() { 43 return nodes; 44 } 45 46 void setNodes(List<Node> nodes) { 47 this.nodes = nodes; 48 } 49 50 51 List<KeyAndValue> getKeyAndValue() { 52 return keyAndValue; 53 } 54 55 // public void setKeyAndValue(List<KeyAndValue> KeyAndValue) { 56 // this.keyAndValue = KeyAndValue; 57 // } 58 59 Node getNextNode() { 60 return nextNode; 61 } 62 63 void setNextNode(Node nextNode) { 64 this.nextNode = nextNode; 65 } 66 67 Node getParantNode() { 68 return parantNode; 69 } 70 71 void setParantNode(Node parantNode) { 72 this.parantNode = parantNode; 73 } 74 75 Node getPreviousNode() { 76 return previousNode; 77 } 78 79 void setPreviousNode(Node previousNode) { 80 this.previousNode = previousNode; 81 } 82 }
定義一個存儲關鍵字和數據的類
1 public class KeyAndValue implements Comparable<KeyAndValue>{ 2 /*存儲索引關鍵字*/ 3 private int key; 4 /*存儲數據*/ 5 private Object value; 6 7 @Override 8 public int compareTo(KeyAndValue o) { 9 //根據key的值升序排列 10 return this.key - o.key; 11 } 12 13 public int getKey() { 14 return key; 15 } 16 17 public void setKey(int key) { 18 this.key = key; 19 } 20 21 public Object getValue() { 22 return value; 23 } 24 25 public void setValue(Object value) { 26 this.value = value; 27 } 28 29 KeyAndValue(int key, Object value) { 30 this.key = key; 31 this.value = value; 32 } 33 }
最后是具體的實現代碼
1 import java.util.*; 2 3 4 public class Btree { 5 private static final String NODE = "NODE"; 6 static final String INT = "INT"; 7 private static final String PRENODE = "PRENODE"; 8 private static final String NEXTNODE = "NEXTNODE"; 9 //B+樹的階數 10 private int rank; 11 //根節點 12 private Node root; 13 //頭結點 14 private Node head; 15 16 Btree(int rank) { 17 this.rank = rank; 18 } 19 20 public Node getRoot() { 21 return root; 22 } 23 24 public void insert(KeyAndValue entry) { 25 List<KeyAndValue> keyAndValues1 = new ArrayList<>(); 26 //插入第一個節點 27 if (head == null) { 28 keyAndValues1.add(entry); 29 head = new Node(null, keyAndValues1, null, null, null); 30 root = new Node(null, keyAndValues1, null, null, null); 31 } else { 32 Node node = head; 33 //遍歷鏈表,找到插入鍵值對對應的節點 34 while (node != null) { 35 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 36 int exitFlag = 0; 37 //如果插入的鍵的值和當前節點鍵值對集合中的某個鍵的值相等,則直接替換value 38 for (KeyAndValue KV : keyAndValues) { 39 if (KV.getKey() == entry.getKey()) { 40 KV.setValue(entry.getValue()); 41 exitFlag = 1; 42 break; 43 } 44 } 45 //如果插入的鍵已經有了,則退出循環 46 if (exitFlag == 1) { 47 break; 48 } 49 //如果當前節點是最后一個節點或者要插入的鍵值對的鍵的值小於下一個節點的鍵的最小值,則直接插入當前節點 50 if (node.getNextNode() == null || node.getNextNode().getKeyAndValue().get(0).getKey() >= entry.getKey()) { 51 splidNode(node, entry); 52 break; 53 } 54 //移動指針 55 node = node.getNextNode(); 56 } 57 } 58 } 59 60 61 //判斷是否需要拆分節點 62 private void splidNode(Node node, KeyAndValue addkeyAndValue) { 63 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 64 65 if (keyAndValues.size() == rank - 1) { 66 //先插入待添加的節點 67 keyAndValues.add(addkeyAndValue); 68 Collections.sort(keyAndValues); 69 //取出當前節點的鍵值對集合 70 //取出原來的key-value集合中間位置的下標 71 int mid = keyAndValues.size() / 2; 72 //取出原來的key-value集合中間位置的鍵 73 int midKey = keyAndValues.get(mid).getKey(); 74 //構造一個新的鍵值對,不是葉子節點的節點不存儲value的信息 75 KeyAndValue midKeyAndValue = new KeyAndValue(midKey, ""); 76 //將中間位置左邊的鍵值對封裝成集合對象 77 List<KeyAndValue> leftKeyAndValues = new ArrayList<>(); 78 for (int i = 0; i < mid; i++) { 79 leftKeyAndValues.add(keyAndValues.get(i)); 80 } 81 //將中間位置右邊邊的鍵值對封裝成集合對象 82 List<KeyAndValue> rightKeyAndValues = new ArrayList<>(); 83 //如果是葉子節點則在原節點中保留上移的key-value,否則原節點刪除上移的key-value 84 int k; 85 if (node.isLeaf()) { 86 k = mid; 87 } else { 88 k = mid + 1; 89 } 90 for (int i = k; i < rank; i++) { 91 rightKeyAndValues.add(keyAndValues.get(i)); 92 } 93 //對左右兩邊的元素重排序 94 Collections.sort(leftKeyAndValues); 95 Collections.sort(rightKeyAndValues); 96 //以mid為界限將當前節點分列成兩個節點,維護前指針和后指針 97 Node rightNode; 98 Node leftNode; 99 // if (node.isLeaf()) { 100 //如果是葉子節點維護前后指針 101 rightNode = new Node(null, rightKeyAndValues, node.getNextNode(), null, node.getParantNode()); 102 leftNode = new Node(null, leftKeyAndValues, rightNode, node.getPreviousNode(), node.getParantNode()); 103 rightNode.setPreviousNode(leftNode); 104 // } else { 105 // //如果不是葉子不維護前后指針 106 // rightNode = new Node(null, rightKeyAndValues, null, null, node.getParantNode()); 107 // leftNode = new Node(null, leftKeyAndValues, null, null, node.getParantNode()); 108 // } 109 //如果當前分裂的節點有孩子節點,設置分裂后節點和孩子節點的關系 110 if (node.getNodes() != null) { 111 //取得所有地孩子節點 112 List<Node> nodes = node.getNodes(); 113 List<Node> leftNodes = new ArrayList<>(); 114 List<Node> rightNodes = new ArrayList<>(); 115 for (Node childNode : nodes) { 116 //取得當前孩子節點的最大鍵值 117 int max = childNode.getKeyAndValue().get(childNode.getKeyAndValue().size() - 1).getKey(); 118 if (max < midKeyAndValue.getKey()) { 119 //小於mid處的鍵的數是左節點的子節點 120 leftNodes.add(childNode); 121 childNode.setParantNode(leftNode); 122 } else { 123 //大於mid處的鍵的數是右節點的子節點 124 rightNodes.add(childNode); 125 childNode.setParantNode(rightNode); 126 } 127 } 128 leftNode.setNodes(leftNodes); 129 rightNode.setNodes(rightNodes); 130 } 131 132 //當前節點的前節點 133 Node preNode = node.getPreviousNode(); 134 //分裂節點后將分裂節點的前節點的后節點設置為左節點 135 if (preNode != null) { 136 preNode.setNextNode(leftNode); 137 } 138 139 //當前節點的后節點 140 Node nextNode = node.getNextNode(); 141 //分裂節點后將分裂節點的后節點的前節點設置為右節點 142 if (nextNode != null) { 143 nextNode.setPreviousNode(rightNode); 144 } 145 146 //如果由頭結點分裂,則分裂后左邊的節點為頭節點 147 if (node == head) { 148 head = leftNode; 149 } 150 151 //父節點的子節點 152 List<Node> childNodes = new ArrayList<>(); 153 childNodes.add(rightNode); 154 childNodes.add(leftNode); 155 //分裂 156 //當前節點無父節點 157 if (node.getParantNode() == null) { 158 //父節點的鍵值對 159 List<KeyAndValue> parentKeyAndValues = new ArrayList<>(); 160 parentKeyAndValues.add(midKeyAndValue); 161 //構造父節點 162 Node parentNode = new Node(childNodes, parentKeyAndValues, null, null, null); 163 //將子節點與父節點關聯 164 rightNode.setParantNode(parentNode); 165 leftNode.setParantNode(parentNode); 166 //當前節點為根節點 167 root = parentNode; 168 } else { 169 Node parentNode = node.getParantNode(); 170 //將原來的孩子節點(除了被拆分的節點)和新的孩子節點(左孩子和右孩子)合並之后與父節點關聯 171 childNodes.addAll(parentNode.getNodes()); 172 //移除正在被拆分的節點 173 childNodes.remove(node); 174 //將子節點與父節點關聯 175 parentNode.setNodes(childNodes); 176 rightNode.setParantNode(parentNode); 177 leftNode.setParantNode(parentNode); 178 if (parentNode.getParantNode() == null) { 179 root = parentNode; 180 } 181 //當前節點有父節點,遞歸調用拆分的方法,將父節點拆分 182 splidNode(parentNode, midKeyAndValue); 183 } 184 } else { 185 keyAndValues.add(addkeyAndValue); 186 //排序 187 Collections.sort(keyAndValues); 188 } 189 } 190 191 192 //打印B+樹 193 void printBtree(Node root) { 194 if (root == this.root) { 195 //打印根節點內的元素 196 printNode(root); 197 System.out.println(); 198 } 199 if (root == null) { 200 return; 201 } 202 203 //打印子節點的元素 204 if (root.getNodes() != null) { 205 //找到最左邊的節點 206 Node leftNode = null; 207 Node tmpNode = null; 208 List<Node> childNodes = root.getNodes(); 209 for (Node node : childNodes) { 210 if (node.getPreviousNode() == null) { 211 leftNode = node; 212 tmpNode = node; 213 } 214 } 215 216 while (leftNode != null) { 217 //從最左邊的節點向右打印 218 printNode(leftNode); 219 System.out.print("|"); 220 leftNode = leftNode.getNextNode(); 221 } 222 System.out.println(); 223 printBtree(tmpNode); 224 } 225 } 226 227 //打印一個節點內的元素 228 private void printNode(Node node) { 229 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 230 for (int i = 0; i < keyAndValues.size(); i++) { 231 if (i != (keyAndValues.size() - 1)) { 232 System.out.print(keyAndValues.get(i).getKey() + ","); 233 } else { 234 System.out.print(keyAndValues.get(i).getKey()); 235 } 236 } 237 } 238 239 public Object search(int key, Node node, String mode) { 240 241 //如果是葉子節點則直接取值 242 if (node.isLeaf()) { 243 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 244 for (KeyAndValue keyAndValue : keyAndValues) { 245 if (keyAndValue.getKey() == key) { 246 switch (mode) { 247 case NODE: 248 return node; 249 case INT: 250 return keyAndValue.getValue(); 251 } 252 } 253 } 254 return null; 255 } 256 257 258 List<Node> nodes = node.getNodes(); 259 //如果尋找的key小於節點的鍵的最小值 260 int minKey = node.getKeyAndValue().get(0).getKey(); 261 if (key < minKey) { 262 for (Node n : nodes) { 263 List<KeyAndValue> keyAndValues = n.getKeyAndValue(); 264 //找到子節點集合中最大鍵小於父節點最小鍵節點 265 if (keyAndValues.get(keyAndValues.size() - 1).getKey() < minKey) { 266 return search(key, n, mode); 267 } 268 } 269 } 270 //如果尋找的key大於節點的鍵的最大值 271 int maxKey = getMaxKeyInNode(node); 272 if (key >= maxKey) { 273 for (Node n : nodes) { 274 List<KeyAndValue> keyAndValues = n.getKeyAndValue(); 275 //找到子節點集合中最小鍵大於等於父節點最小大鍵節點 276 if (keyAndValues.get(0).getKey() >= maxKey) { 277 return search(key, n, mode); 278 } 279 } 280 } 281 282 //如果尋找的key在最大值和最小值之間,首先定位到最窄的區間 283 int min = getLeftBoundOfKey(node, key); 284 int max = getRightBoundOfKey(node, key); 285 286 287 //去所有的子節點中找鍵的范圍在min和max之間的節點 288 for (Node n : nodes) { 289 List<KeyAndValue> kvs = n.getKeyAndValue(); 290 //找到子節點集合中鍵的范圍在min和max之間的節點 291 if (kvs.get(0).getKey() >= min && kvs.get(kvs.size() - 1).getKey() < max) { 292 return search(key, n, mode); 293 } 294 } 295 return null; 296 } 297 298 299 public boolean delete(int key) { 300 System.out.println("delete:" + key); 301 System.out.println(); 302 303 //首先找到要刪除的key所在的節點 304 Node deleteNode = (Node) search(key, root, NODE); 305 //如果沒找到則刪除失敗 306 if (deleteNode == null) { 307 return false; 308 } 309 310 if (deleteNode == root) { 311 delKeyAndValue(root.getKeyAndValue(), key); 312 return true; 313 } 314 315 if (deleteNode == head && isNeedMerge(head)) { 316 head = head.getNextNode(); 317 } 318 319 return merge(deleteNode, key); 320 } 321 322 323 //平衡當前節點和前節點或者后節點的數量,使兩者的數量都滿足條件 324 private boolean balanceNode(Node node, Node bratherNode, String nodeType) { 325 if (bratherNode == null) { 326 return false; 327 } 328 List<KeyAndValue> delKeyAndValues = node.getKeyAndValue(); 329 if (isMoreElement(bratherNode)) { 330 List<KeyAndValue> bratherKeyAndValues = bratherNode.getKeyAndValue(); 331 int bratherSize = bratherKeyAndValues.size(); 332 //兄弟節點刪除挪走的鍵值對 333 KeyAndValue keyAndValue = null; 334 KeyAndValue keyAndValue1; 335 switch (nodeType) { 336 case PRENODE: 337 keyAndValue = bratherKeyAndValues.remove(bratherSize - 1); 338 keyAndValue1 = getKeyAndValueinMinAndMax(node.getParantNode(), keyAndValue.getKey(), getMinKeyInNode(node)); 339 keyAndValue1.setKey(keyAndValue.getKey()); 340 break; 341 case NEXTNODE: 342 keyAndValue = bratherKeyAndValues.remove(0); 343 keyAndValue1 = getKeyAndValueinMinAndMax(node.getParantNode(), getMaxKeyInNode(node), keyAndValue.getKey()); 344 keyAndValue1.setKey(bratherKeyAndValues.get(0).getKey()); 345 break; 346 } 347 //當前節點添加從前一個節點得來的鍵值對 348 delKeyAndValues.add(keyAndValue); 349 350 //對鍵值對重排序 351 Collections.sort(delKeyAndValues); 352 return true; 353 } 354 return false; 355 } 356 357 public boolean merge(Node node, int key) { 358 List<KeyAndValue> delKeyAndValues = node.getKeyAndValue(); 359 //首先刪除該key-vaule 360 delKeyAndValue(delKeyAndValues, key); 361 //如果要刪除的節點的鍵值對的數目小於節點最大鍵值對數目*填充因子 362 if (isNeedMerge(node)) { 363 Boolean isBalance; 364 //如果左節點有富余的鍵值對,則取一個到當前節點 365 Node preNode = getPreviousNode(node); 366 isBalance = balanceNode(node, preNode, PRENODE); 367 //如果此時已經平衡,則已經刪除成功 368 if (isBalance) return true; 369 370 //如果右兄弟節點有富余的鍵值對,則取一個到當前節點 371 Node nextNode = getNextNode(node); 372 isBalance = balanceNode(node, nextNode, NEXTNODE); 373 374 return isBalance || mergeNode(node, key); 375 } else { 376 return true; 377 } 378 } 379 380 //合並節點 381 //key 待刪除的key 382 private boolean mergeNode(Node node, int key) { 383 if (node.isRoot()) { 384 return false; 385 } 386 Node preNode; 387 Node nextNode; 388 Node parentNode = node.getParantNode(); 389 List<Node> childNodes = parentNode.getNodes(); 390 List<Node> childNodes1 = node.getNodes(); 391 List<KeyAndValue> parentKeyAndValue = parentNode.getKeyAndValue(); 392 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 393 394 if (node.isLeaf()) { 395 if (parentKeyAndValue.size() == 1 && parentNode != root) { 396 return true; 397 } 398 preNode = getPreviousNode(node); 399 nextNode = getNextNode(node); 400 if (preNode != null) { 401 List<KeyAndValue> preKeyAndValues = preNode.getKeyAndValue(); 402 keyAndValues.addAll(preKeyAndValues); 403 if (preNode.isHead()) { 404 head = node; 405 node.setPreviousNode(null); 406 } else { 407 preNode.getPreviousNode().setNextNode(node); 408 node.setPreviousNode(preNode.getPreviousNode()); 409 } 410 //將合並后節點的后節點設置為當前節點的后節點 411 preNode.setNextNode(node.getNextNode()); 412 KeyAndValue keyAndValue = getKeyAndValueinMinAndMax(parentNode, getMinKeyInNode(preNode), key); 413 delKeyAndValue(parentKeyAndValue, keyAndValue.getKey()); 414 if (parentKeyAndValue.isEmpty()) { 415 root = node; 416 } else { 417 //刪除當前節點 418 childNodes.remove(preNode); 419 } 420 Collections.sort(keyAndValues); 421 merge(parentNode, key); 422 return true; 423 } 424 425 if (nextNode != null) { 426 List<KeyAndValue> nextKeyAndValues = nextNode.getKeyAndValue(); 427 keyAndValues.addAll(nextKeyAndValues); 428 if (nextNode.isTail()) { 429 node.setPreviousNode(null); 430 } else { 431 nextNode.getNextNode().setPreviousNode(node); 432 node.setNextNode(nextNode.getNextNode()); 433 } 434 435 KeyAndValue keyAndValue = getKeyAndValueinMinAndMax(parentNode, key, getMinKeyInNode(nextNode)); 436 delKeyAndValue(parentKeyAndValue, keyAndValue.getKey()); 437 if (parentKeyAndValue.isEmpty()) { 438 root = node; 439 node.setParantNode(null); 440 } else { 441 //刪除當前節點 442 childNodes.remove(nextNode); 443 } 444 Collections.sort(keyAndValues); 445 merge(parentNode, key); 446 return true; 447 } 448 //前節點和后節點都等於null那么是root節點 449 return false; 450 } else { 451 preNode = getPreviousNode(node); 452 nextNode = getNextNode(node); 453 if (preNode != null) { 454 //將前一個節點和當前節點還有父節點中的相應Key-value合並 455 List<KeyAndValue> preKeyAndValues = preNode.getKeyAndValue(); 456 preKeyAndValues.addAll(keyAndValues); 457 int min = getMaxKeyInNode(preNode); 458 int max = getMinKeyInNode(node); 459 //父節點中移除這個key-value 460 KeyAndValue keyAndValue = getKeyAndValueinMinAndMax(parentNode, min, max); 461 parentKeyAndValue.remove(keyAndValue); 462 if (parentKeyAndValue.isEmpty()) { 463 root = preNode; 464 node.setParantNode(null); 465 preNode.setParantNode(null); 466 } else { 467 childNodes.remove(node); 468 } 469 assert nextNode != null; 470 preNode.setNextNode(nextNode.getNextNode()); 471 //前節點加上一個當前節點的所有子節點中最小key的key-value 472 KeyAndValue minKeyAndValue = getMinKeyAndValueInChildNode(node); 473 assert minKeyAndValue != null; 474 KeyAndValue keyAndValue1 = new KeyAndValue(minKeyAndValue.getKey(), minKeyAndValue.getValue()); 475 preKeyAndValues.add(keyAndValue1); 476 List<Node> preChildNodes = preNode.getNodes(); 477 preChildNodes.addAll(node.getNodes()); 478 //將當前節點的孩子節點的父節點設為當前節點的后節點 479 for (Node node1 : childNodes1) { 480 node1.setParantNode(preNode); 481 } 482 Collections.sort(preKeyAndValues); 483 merge(parentNode, key); 484 return true; 485 } 486 487 if (nextNode != null) { 488 //將后一個節點和當前節點還有父節點中的相應Key-value合並 489 List<KeyAndValue> nextKeyAndValues = nextNode.getKeyAndValue(); 490 nextKeyAndValues.addAll(keyAndValues); 491 492 int min = getMaxKeyInNode(node); 493 int max = getMinKeyInNode(nextNode); 494 //父節點中移除這個key-value 495 KeyAndValue keyAndValue = getKeyAndValueinMinAndMax(parentNode, min, max); 496 parentKeyAndValue.remove(keyAndValue); 497 childNodes.remove(node); 498 if (parentKeyAndValue.isEmpty()) { 499 root = nextNode; 500 nextNode.setParantNode(null); 501 } else { 502 childNodes.remove(node); 503 } 504 nextNode.setPreviousNode(node.getPreviousNode()); 505 //后節點加上一個當后節點的所有子節點中最小key的key-value 506 KeyAndValue minKeyAndValue = getMinKeyAndValueInChildNode(nextNode); 507 assert minKeyAndValue != null; 508 KeyAndValue keyAndValue1 = new KeyAndValue(minKeyAndValue.getKey(), minKeyAndValue.getValue()); 509 nextKeyAndValues.add(keyAndValue1); 510 List<Node> nextChildNodes = nextNode.getNodes(); 511 nextChildNodes.addAll(node.getNodes()); 512 //將當前節點的孩子節點的父節點設為當前節點的后節點 513 for (Node node1 : childNodes1) { 514 node1.setParantNode(nextNode); 515 } 516 Collections.sort(nextKeyAndValues); 517 merge(parentNode, key); 518 return true; 519 } 520 return false; 521 } 522 } 523 524 //得到當前節點的前節點 525 private Node getPreviousNode(Node node) { 526 if (node.isRoot()) { 527 return null; 528 } 529 530 Node parentNode = node.getParantNode(); 531 //得到兄弟節點 532 List<Node> nodes = parentNode.getNodes(); 533 List<KeyAndValue> keyAndValues = new ArrayList<>(); 534 for (Node n : nodes) { 535 List<KeyAndValue> list = n.getKeyAndValue(); 536 int maxKeyAndValue = list.get(list.size() - 1).getKey(); 537 if (maxKeyAndValue < getMinKeyInNode(node)) { 538 keyAndValues.add(new KeyAndValue(maxKeyAndValue, n)); 539 } 540 } 541 Collections.sort(keyAndValues); 542 if (keyAndValues.isEmpty()) { 543 return null; 544 } 545 return (Node) keyAndValues.get(keyAndValues.size() - 1).getValue(); 546 } 547 548 549 //得到當前節點的后節點 550 private Node getNextNode(Node node) { 551 if (node.isRoot()) { 552 return null; 553 } 554 555 Node parentNode = node.getParantNode(); 556 //得到兄弟節點 557 List<Node> nodes = parentNode.getNodes(); 558 List<KeyAndValue> keyAndValues = new ArrayList<>(); 559 for (Node n : nodes) { 560 List<KeyAndValue> list = n.getKeyAndValue(); 561 int minKeyAndValue = list.get(0).getKey(); 562 if (minKeyAndValue > getMaxKeyInNode(node)) { 563 keyAndValues.add(new KeyAndValue(minKeyAndValue, n)); 564 } 565 } 566 Collections.sort(keyAndValues); 567 if (keyAndValues.isEmpty()) { 568 return null; 569 } 570 return (Node) keyAndValues.get(0).getValue(); 571 } 572 573 574 private int getMinKeyInNode(Node node) { 575 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 576 return keyAndValues.get(0).getKey(); 577 } 578 579 private int getMaxKeyInNode(Node node) { 580 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 581 return keyAndValues.get(keyAndValues.size() - 1).getKey(); 582 } 583 584 585 private int getLeftBoundOfKey(Node node, int key) { 586 int left = 0; 587 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 588 for (int i = 0; i < keyAndValues.size(); i++) { 589 if (keyAndValues.get(i).getKey() <= key && keyAndValues.get(i + 1).getKey() > key) { 590 left = keyAndValues.get(i).getKey(); 591 break; 592 } 593 } 594 return left; 595 } 596 597 private int getRightBoundOfKey(Node node, int key) { 598 int right = 0; 599 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 600 for (int i = 0; i < keyAndValues.size(); i++) { 601 if (keyAndValues.get(i).getKey() <= key && keyAndValues.get(i + 1).getKey() > key) { 602 right = keyAndValues.get(i + 1).getKey(); 603 break; 604 } 605 } 606 return right; 607 } 608 609 610 private void delKeyAndValue(List<KeyAndValue> keyAndValues, int key) { 611 for (KeyAndValue keyAndValue : keyAndValues) { 612 if (keyAndValue.getKey() == key) { 613 keyAndValues.remove(keyAndValue); 614 break; 615 } 616 } 617 } 618 619 //找到node的鍵值對中在min和max中的鍵值對 620 private KeyAndValue getKeyAndValueinMinAndMax(Node node, int min, int max) { 621 if (node == null) { 622 return null; 623 } 624 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 625 KeyAndValue keyAndValue = null; 626 for (KeyAndValue k : keyAndValues) { 627 if (k.getKey() > min && k.getKey() <= max) { 628 keyAndValue = k; 629 break; 630 } 631 } 632 return keyAndValue; 633 } 634 635 // private KeyAndValue getMaxKeyAndValueInChildNode(Node node) { 636 // if (node.getNodes() == null || node.getNodes().isEmpty()) { 637 // return null; 638 // } 639 // List<KeyAndValue> sortKeyAndValues = new ArrayList<>(); 640 // List<Node> childNodes = node.getNodes(); 641 // for (Node childNode : childNodes) { 642 // List<KeyAndValue> keyAndValues = childNode.getKeyAndValue(); 643 // KeyAndValue maxKeyAndValue = keyAndValues.get(keyAndValues.size() - 1); 644 // sortKeyAndValues.add(maxKeyAndValue); 645 // } 646 // Collections.sort(sortKeyAndValues); 647 // return sortKeyAndValues.get(sortKeyAndValues.size() - 1); 648 // } 649 650 private KeyAndValue getMinKeyAndValueInChildNode(Node node) { 651 if (node.getNodes() == null || node.getNodes().isEmpty()) { 652 return null; 653 } 654 List<KeyAndValue> sortKeyAndValues = new ArrayList<>(); 655 List<Node> childNodes = node.getNodes(); 656 for (Node childNode : childNodes) { 657 List<KeyAndValue> keyAndValues = childNode.getKeyAndValue(); 658 KeyAndValue minKeyAndValue = keyAndValues.get(0); 659 sortKeyAndValues.add(minKeyAndValue); 660 } 661 Collections.sort(sortKeyAndValues); 662 return sortKeyAndValues.get(0); 663 } 664 665 private boolean isNeedMerge(Node node) { 666 if (node == null) { 667 return false; 668 } 669 List<KeyAndValue> keyAndValues = node.getKeyAndValue(); 670 return keyAndValues.size() < rank / 2; 671 } 672 673 //判斷一個節點是否有富余的鍵值對 674 private boolean isMoreElement(Node node) { 675 return node != null && (node.getKeyAndValue().size() > rank / 2); 676 } 677 }
測試代碼:
1 public class Main { 2 3 public static void main(String[] args) { 4 Btree btree = new Btree(4 ); 5 KeyAndValue keyAndValue = new KeyAndValue(1,"123"); 6 KeyAndValue keyAndValue1 = new KeyAndValue(2,"123"); 7 KeyAndValue keyAndValue2 = new KeyAndValue(3,"123"); 8 KeyAndValue keyAndValue3 = new KeyAndValue(4,"123"); 9 KeyAndValue keyAndValue4 = new KeyAndValue(5,"123"); 10 KeyAndValue keyAndValue5 = new KeyAndValue(6,"123"); 11 KeyAndValue keyAndValue6 = new KeyAndValue(7,"12300"); 12 KeyAndValue keyAndValue7 = new KeyAndValue(8,"546"); 13 KeyAndValue keyAndValue8 = new KeyAndValue(9,"123"); 14 KeyAndValue keyAndValue9 = new KeyAndValue(10,"123"); 15 KeyAndValue keyAndValue10 = new KeyAndValue(11,"123"); 16 KeyAndValue keyAndValue11 = new KeyAndValue(12,"123"); 17 KeyAndValue keyAndValue12 = new KeyAndValue(13,"123"); 18 KeyAndValue keyAndValue14 = new KeyAndValue(15,"12345"); 19 KeyAndValue keyAndValue15 = new KeyAndValue(16,"12345"); 20 KeyAndValue keyAndValue16 = new KeyAndValue(17,"12345"); 21 KeyAndValue keyAndValue17 = new KeyAndValue(18,"12345"); 22 KeyAndValue keyAndValue18 = new KeyAndValue(19,"12345"); 23 KeyAndValue keyAndValue19 = new KeyAndValue(20,"12345"); 24 KeyAndValue keyAndValue20 = new KeyAndValue(21,"12345"); 25 26 btree.insert(keyAndValue); 27 btree.insert(keyAndValue5); 28 btree.insert(keyAndValue9); 29 btree.insert(keyAndValue1); 30 btree.insert(keyAndValue7); 31 btree.insert(keyAndValue10); 32 btree.insert(keyAndValue17); 33 btree.insert(keyAndValue2); 34 btree.insert(keyAndValue14); 35 btree.insert(keyAndValue16); 36 btree.insert(keyAndValue11); 37 btree.insert(keyAndValue12); 38 btree.insert(keyAndValue3); 39 btree.insert(keyAndValue8); 40 btree.insert(keyAndValue18); 41 btree.insert(keyAndValue15); 42 btree.insert(keyAndValue4); 43 btree.insert(keyAndValue19); 44 btree.insert(keyAndValue6); 45 btree.insert(keyAndValue20); 46 47 48 btree.printBtree(btree.getRoot()); 49 50 btree.delete(1); 51 btree.printBtree(btree.getRoot()); 52 53 btree.delete(0); 54 btree.printBtree(btree.getRoot()); 55 56 btree.delete(2); 57 btree.printBtree(btree.getRoot()); 58 59 btree.delete(11); 60 btree.printBtree(btree.getRoot()); 61 62 btree.delete(3); 63 btree.printBtree(btree.getRoot()); 64 65 btree.delete(4); 66 btree.printBtree(btree.getRoot()); 67 68 btree.delete(5); 69 btree.printBtree(btree.getRoot()); 70 71 btree.delete(9); 72 btree.printBtree(btree.getRoot()); 73 74 btree.delete(6); 75 btree.printBtree(btree.getRoot()); 76 77 btree.delete(13); 78 btree.printBtree(btree.getRoot()); 79 80 btree.delete(7); 81 btree.printBtree(btree.getRoot()); 82 83 btree.delete(10); 84 btree.printBtree(btree.getRoot()); 85 86 btree.delete(18); 87 btree.printBtree(btree.getRoot()); 88 89 btree.delete(8); 90 btree.printBtree(btree.getRoot()); 91 92 btree.delete(12); 93 btree.printBtree(btree.getRoot()); 94 95 btree.delete(20); 96 btree.printBtree(btree.getRoot()); 97 98 btree.delete(19); 99 btree.printBtree(btree.getRoot()); 100 101 btree.delete(15); 102 btree.printBtree(btree.getRoot()); 103 104 btree.delete(17); 105 btree.printBtree(btree.getRoot()); 106 107 108 110 } 111 }
測試結果:
8,12 3,6|10|15,18,20| 1,2|3,4,5|6,7|8,9|10,11|12,13|15,16,17|18,19|20,21| delete:1 8,12 4,6|10|15,18,20| 2,3|4,5|6,7|8,9|10,11|12,13|15,16,17|18,19|20,21| delete:0 8,12 4,6|10|15,18,20| 2,3|4,5|6,7|8,9|10,11|12,13|15,16,17|18,19|20,21| delete:2 12 6,8,10|15,18,20| 3,4,5|6,7|8,9|10,11|12,13|15,16,17|18,19|20,21| delete:11 12 6,8|15,18,20| 3,4,5|6,7|8,9,10|12,13|15,16,17|18,19|20,21| delete:3 12 6,8|15,18,20| 4,5|6,7|8,9,10|12,13|15,16,17|18,19|20,21| delete:4 18 8,15|18,20| 5,6,7|8,9,10|12,13|15,16,17|18,19|20,21| delete:5 18 8,15|18,20| 6,7|8,9,10|12,13|15,16,17|18,19|20,21| delete:9 18 8,15|18,20| 6,7|8,10|12,13|15,16,17|18,19|20,21| delete:6 12,15,18,20 7,8,10|12,13|15,16,17|18,19|20,21| delete:13 10,15,18,20 7,8|10,12|15,16,17|18,19|20,21| delete:7 15,18,20 8,10,12|15,16,17|18,19|20,21| delete:10 15,18,20 8,12|15,16,17|18,19|20,21| delete:18 15,17,20 8,12|15,16|17,19|20,21| delete:8 17,20 12,15,16|17,19|20,21| delete:12 17,20 15,16|17,19|20,21| delete:20 17 15,16|17,19,21| delete:19 17 15,16|17,21| delete:15 16,17,21 delete:17 16,21