B樹、B+樹的java實現
阿新 • • 發佈:2018-12-25
一、B樹的定義
在定義B樹之前,首先明確一個概念,就是什麼是樹的階?
樹的階指的是一個結點最多能有多少棵子樹。例如:二叉樹的階就是2。
這個要跟結點的度區分開來,度是基於單個結點的,而階是針對整棵樹的。可以理解為樹的階是用來限制每個結點的度的。
B樹,又稱B-樹,一棵m階的B樹,或為空樹,或為滿足下列特性的m叉樹:
(1)樹中每個結點至多有m棵子樹。【解釋:因為樹的階是m,所有這個是必然】
(2)若根結點不是葉子節點,則至少有兩棵子樹。
(3)除根結點之外的所有非葉子結點至少有⌈m/2⌉棵子樹。【解釋:第一條是用來限制所有節點度的最大值,2、3兩條是用來限制根結點和非葉子結點度的最小值】
(4)所有的非葉子結點中包含下列資訊資料
(n,P0,K0,P1,K1,P2,···,Kn-1,Pn)
其中,K[i] (i=0,···,n-1)為關鍵字,切K[i] < K[i+1](i=0,···,n-1),P[i] (i=0,1,···,n-1)為指向子樹根結點的指標,且指標P[i]所指向的子樹中的所有結點的關鍵字均小於K[i] (i=0,···,n-1),P[i+1]所指向的子樹中的所有結點的關鍵字均大於K[i]。n為關鍵字的關鍵字的個數,且⌈m/2⌉-1 ≤ n ≤ m-1。【解釋:指的關鍵字的左子樹都比它小,右子樹都比它大】
(5)所有葉子結點位於同一層
示例,3階B樹(m=3):
二、B樹的增刪改查
1、B樹的模型
package com.ghs.algorithm;
import java.util.List;
public class BTNode<K extends Comparable> {
/** 關鍵字的個數 */
private int number = 0;
/** 關鍵字,0號單元未使用 */
private List<K> keys;
/** 子樹 */
private List<BTNode> children;
}
package com.ghs.algorithm;
public class BTree<K extends Comparable<K>>{
/** 根節點 */
private BTNode root;
/** 階 */
private int order;
}
2、B樹的查詢操作
/**
* @title 查詢key
* @author ghs
* @date 2017/11/10 21:53
* @param
* @return
*/
public Result getKey(K key){
BTNode preNode = null;
BTNode node = root;
boolean found = false;
int i = 0;
while (node != null && !found){
i = index(node, key);
if(node.getKey(i).equals(key)){
found = true;
}else{
preNode = node;
node = node.getChildren(i);
}
}
return new Result(found ? node:preNode, i, found);
}
/**
* @title 查詢key在node中的位置
* @author ghs
* @date 2017/11/10 19:41
* @param
* @return
*/
private int index(BTNode<K> node, K key){
//在keys[1...keyNum]中查詢,使得keys[i]<= key < keys[i+1](0<i<keyNum-1)
for (int i=0; i<node.getNumber(); i++){
if (key.compareTo(node.getKey(i)) <= 0){
return i;
}
}
return node.getNumber();
}
3、B樹的插入
public void addKey(K key){
Result result = getKey(key);
BTNode<K> node = result.getNode();
int position = result.getPosition();
K k = key;
BTNode<K> rightNode = null;
while (node!=null){
add(node, position, k, rightNode);
int number = node.getNumber();
if(number < order){
return;
}else {
int s = number%2==0 ? number/2 : number/2+1;
split(node, s, rightNode);
k = node.getKey(s);
node = node.getParent();
if (node != null) {
position = index(node, k);
}
}
}
newRoot(key);
}
private void split(BTNode<K> node, int s, BTNode<K> newNode){
int number = node.getNumber();
List<K> keys = node.getKeys();
List<BTNode> children = node.getChildren();
node.setKeys(keys.subList(0, s-1));
node.setChildren(children.subList(0, s));
node.setNumber(s-1);
newNode.setKeys(keys.subList(s, number-1));
newNode.setChildren(children.subList(s, number));
newNode.setNumber(number-s);
}
private BTNode newRoot(K key){
BTNode node = new BTNode();
node.addKey(0, key);
node.addChildren(0, nullBTNode);
node.addChildren(1, nullBTNode);
node.setNumber(1);
return node;
}