java 树算法_B+树的算法(java实现)

1 import java.util.*;2

3

4 public classBtree {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 intrank;11 //根节点

12 privateNode root;13 //头结点

14 privateNode head;15

16 Btree(intrank) {17 this.rank =rank;18 }19

20 publicNode getRoot() {21 returnroot;22 }23

24 public voidinsert(KeyAndValue entry) {25 List 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 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 voidsplidNode(Node node, KeyAndValue addkeyAndValue) {63 List 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 leftKeyAndValues = new ArrayList<>();78 for (int i = 0; i < mid; i++) {79 leftKeyAndValues.add(keyAndValues.get(i));80 }81 //将中间位置右边边的键值对封装成集合对象

82 List rightKeyAndValues = new ArrayList<>();83 //如果是叶子节点则在原节点中保留上移的key-value,否则原节点删除上移的key-value

84 intk;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 nodes =node.getNodes();113 List leftNodes = new ArrayList<>();114 List rightNodes = new ArrayList<>();115 for(Node childNode : nodes) {116 //取得当前孩子节点的最大键值

117 int max = childNode.getKeyAndValue().get(childNode.getKeyAndValue().size() - 1).getKey();118 if (max

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 childNodes = new ArrayList<>();153 childNodes.add(rightNode);154 childNodes.add(leftNode);155 //分裂156 //当前节点无父节点

157 if (node.getParantNode() == null) {158 //父节点的键值对

159 List 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 voidprintBtree(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 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 voidprintNode(Node node) {229 List 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(intkey, Node node, String mode) {240

241 //如果是叶子节点则直接取值

242 if(node.isLeaf()) {243 List keyAndValues =node.getKeyAndValue();244 for(KeyAndValue keyAndValue : keyAndValues) {245 if (keyAndValue.getKey() ==key) {246 switch(mode) {247 caseNODE:248 returnnode;249 caseINT:250 returnkeyAndValue.getValue();251 }252 }253 }254 return null;255 }256

257

258 List nodes =node.getNodes();259 //如果寻找的key小于节点的键的最小值

260 int minKey = node.getKeyAndValue().get(0).getKey();261 if (key keyAndValues =n.getKeyAndValue();264 //找到子节点集合中最大键小于父节点最小键节点

265 if (keyAndValues.get(keyAndValues.size() - 1).getKey()

271 int maxKey =getMaxKeyInNode(node);272 if (key >=maxKey) {273 for(Node n : nodes) {274 List keyAndValues =n.getKeyAndValue();275 //找到子节点集合中最小键大于等于父节点最小大键节点

276 if (keyAndValues.get(0).getKey() >=maxKey) {277 returnsearch(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 kvs =n.getKeyAndValue();290 //找到子节点集合中键的范围在min和max之间的节点

291 if (kvs.get(0).getKey() >= min && kvs.get(kvs.size() - 1).getKey()

298

299 public boolean delete(intkey) {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 returnmerge(deleteNode, key);320 }321

322

323 //平衡当前节点和前节点或者后节点的数量,使两者的数量都满足条件

324 private booleanbalanceNode(Node node, Node bratherNode, String nodeType) {325 if (bratherNode == null) {326 return false;327 }328 List delKeyAndValues =node.getKeyAndValue();329 if(isMoreElement(bratherNode)) {330 List bratherKeyAndValues =bratherNode.getKeyAndValue();331 int bratherSize =bratherKeyAndValues.size();332 //兄弟节点删除挪走的键值对

333 KeyAndValue keyAndValue = null;334 KeyAndValue keyAndValue1;335 switch(nodeType) {336 casePRENODE:337 keyAndValue = bratherKeyAndValues.remove(bratherSize - 1);338 keyAndValue1 =getKeyAndValueinMinAndMax(node.getParantNode(), keyAndValue.getKey(), getMinKeyInNode(node));339 keyAndValue1.setKey(keyAndValue.getKey());340 break;341 caseNEXTNODE: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, intkey) {358 List 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, intkey) {383 if(node.isRoot()) {384 return false;385 }386 Node preNode;387 Node nextNode;388 Node parentNode =node.getParantNode();389 List childNodes =parentNode.getNodes();390 List childNodes1 =node.getNodes();391 List parentKeyAndValue =parentNode.getKeyAndValue();392 List 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 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 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 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 = newKeyAndValue(minKeyAndValue.getKey(), minKeyAndValue.getValue());475 preKeyAndValues.add(keyAndValue1);476 List 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 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 = newKeyAndValue(minKeyAndValue.getKey(), minKeyAndValue.getValue());509 nextKeyAndValues.add(keyAndValue1);510 List 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 privateNode getPreviousNode(Node node) {526 if(node.isRoot()) {527 return null;528 }529

530 Node parentNode =node.getParantNode();531 //得到兄弟节点

532 List nodes =parentNode.getNodes();533 List keyAndValues = new ArrayList<>();534 for(Node n : nodes) {535 List list =n.getKeyAndValue();536 int maxKeyAndValue = list.get(list.size() - 1).getKey();537 if (maxKeyAndValue

548

549 //得到当前节点的后节点

550 privateNode getNextNode(Node node) {551 if(node.isRoot()) {552 return null;553 }554

555 Node parentNode =node.getParantNode();556 //得到兄弟节点

557 List nodes =parentNode.getNodes();558 List keyAndValues = new ArrayList<>();559 for(Node n : nodes) {560 List list =n.getKeyAndValue();561 int minKeyAndValue = list.get(0).getKey();562 if (minKeyAndValue >getMaxKeyInNode(node)) {563 keyAndValues.add(newKeyAndValue(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 intgetMinKeyInNode(Node node) {575 List keyAndValues =node.getKeyAndValue();576 return keyAndValues.get(0).getKey();577 }578

579 private intgetMaxKeyInNode(Node node) {580 List keyAndValues =node.getKeyAndValue();581 return keyAndValues.get(keyAndValues.size() - 1).getKey();582 }583

584

585 private int getLeftBoundOfKey(Node node, intkey) {586 int left = 0;587 List 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 returnleft;595 }596

597 private int getRightBoundOfKey(Node node, intkey) {598 int right = 0;599 List 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 returnright;607 }608

609

610 private void delKeyAndValue(List keyAndValues, intkey) {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, intmax) {621 if (node == null) {622 return null;623 }624 List 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 returnkeyAndValue;633 }634

635 //private KeyAndValue getMaxKeyAndValueInChildNode(Node node) {636 //if (node.getNodes() == null || node.getNodes().isEmpty()) {637 //return null;638 //}639 //List sortKeyAndValues = new ArrayList<>();640 //List childNodes = node.getNodes();641 //for (Node childNode : childNodes) {642 //List 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 privateKeyAndValue getMinKeyAndValueInChildNode(Node node) {651 if (node.getNodes() == null ||node.getNodes().isEmpty()) {652 return null;653 }654 List sortKeyAndValues = new ArrayList<>();655 List childNodes =node.getNodes();656 for(Node childNode : childNodes) {657 List 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 booleanisNeedMerge(Node node) {666 if (node == null) {667 return false;668 }669 List keyAndValues =node.getKeyAndValue();670 return keyAndValues.size() < rank / 2;671 }672

673 //判断一个节点是否有富余的键值对

674 private booleanisMoreElement(Node node) {675 return node != null && (node.getKeyAndValue().size() > rank / 2);676 }677 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值