版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37885641/article/details/83721223
一、java Bean
package com.hgldp.web.pojo;
import java.util.LinkedList;
/**
* @author hgl
* @data 2018年11月3日
* @description b-tree 结点
*/
public class BSTNode {
/*
* 关键字数量
*/
private int keynum;
/*
* 关键字集合
*/
private LinkedList<Integer> keys;
/*
* 孩子结点的集合
*/
private LinkedList<BSTNode> childs;
/*
* 父结点
*/
private BSTNode parent;
public int getKeynum() {
return keynum;
}
public void setKeynum(int keynum) {
this.keynum = keynum;
}
public LinkedList<Integer> getKeys() {
return keys;
}
public void setKeys(LinkedList<Integer> keys) {
this.keys = keys;
}
public LinkedList<BSTNode> getChilds() {
return childs;
}
public void setChilds(LinkedList<BSTNode> childs) {
this.childs = childs;
}
public BSTNode getParent() {
return parent;
}
public void setParent(BSTNode parent) {
this.parent = parent;
}
@Override
public String toString() {
return "BSTNode [keynum=" + keynum + ", keys=" + keys + ", childs=" + childs + ", parent=" + parent + "]";
}
}
package com.hgldp.web.pojo;
/**
* @author hgl
* @data 2018年11月3日
* @description 查找的结果
*/
public class Result {
/*
* 查找到的结点(如果未找到就是可以插入到的结点)
*/
private BSTNode ptr;
/*
* 查找到的在集合中的位置(如果未找到即为可以插入的位置)
*/
private int i;
/*
* 查找的结果的标志
* false 未找到
* true 找到
*/
private boolean tag;
public Result(BSTNode ptr, int i, boolean tag) {
this.ptr = ptr;
this.i = i;
this.tag = tag;
}
public BSTNode getPtr() {
return ptr;
}
public void setPtr(BSTNode ptr) {
this.ptr = ptr;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public boolean isTag() {
return tag;
}
public void setTag(boolean tag) {
this.tag = tag;
}
@Override
public String toString() {
return "Result [ptr=" + ptr + ", i=" + i + ", tag=" + tag + "]";
}
}
二、B-Tree
/**
* @author hgl
* @data 2018年11月3日
* @description b-tree 树
*/
public class BTree {
/*
* b-tree的介
*/
private int degree;
/*
* b-tree的根结点
*/
private BSTNode root;
public int getDegree() {
return degree;
}
public void setDegree(int degree) {
this.degree = degree;
}
public BSTNode getRoot() {
return root;
}
public void setRoot(BSTNode root) {
this.root = root;
}
public BTree(int degree,BSTNode root) {
this.degree = degree;
this.root = root;
}
/**
* Result
* @param T 待查找的结点
* @param key 待查找的关键字
* @return
* description:搜索b-tree
*/
private Result searchTree(BSTNode T,int key){
BSTNode p = T,q = null;
boolean found = false;
int i = 0;
while(p !=null && !found){
i = search(p,key);
if(i>=0 && p.getKeys().get(i) == key){
found = true;
}else{
q = p;
p = p.getChilds().get(i);
}
}
if(found){
return new Result(p,i,true);
}
return new Result(q,i,false);//如果没找到,就返回可以插入的结点及位置
}
public boolean insertKey(int key){
Result result = searchTree(root,key);
if(!result.isTag()){
return insertBTree(key, result.getPtr(), result.getI());
}
return false;
}
/**
* int
* @param p 待查找的结点
* @param key 待查找的关键字
* @return
* description:查找
*/
private int search(BSTNode p, int key) {
for(int i = 1;i<=p.getKeynum();i++){
if(p.getKeys().get(i)>key){
return i-1;
}else if(p.getKeys().get(i)== key){
return i;
}
}
return p.getKeynum();
}
/**
* boolean
* @param key 关键字
* @param q 待插入的结点
* @param i 插入的位置
* @return
* description:
*/
public boolean insertBTree(int key,BSTNode q,int i){
int x = key,s;
BSTNode ap = null,tmp = null;
boolean finished = false;
while(q !=null && !finished){
insert(q,i,x,ap);
if(q.getKeynum() < degree){
finished = true;
}else{
s = degree%2 == 0?degree/2 : (degree/2+1);
x = q.getKeys().get(s);
ap = new BSTNode();
split(q,s,ap);
tmp = q;
q = q.getParent();
if(q!=null){
i = search(q, x);
}
}
}
if(!finished){
root = tmp;
newRoot(q,x,ap);//当BTree是空树或根结点已经分裂未结点q和ap
}
return false;
}
/**
* void
* @param q
* @param x
* @param ap
* description:更新根结点
*/
private void newRoot(BSTNode q, int x, BSTNode ap) {
q = new BSTNode();
q.setChilds(new LinkedList<BSTNode>());
q.setKeys(new LinkedList<Integer>());
q.setKeynum(1);
q.setParent(null);
q.getKeys().add(-1);
q.getChilds().add(root);
q.getKeys().add(x);
q.getChilds().add(ap);
for(int i =0;i<=q.getKeynum();i++){
if(q.getChilds().get(i) != null){
q.getChilds().get(i).setParent(q);
}
}
root = q;
}
/**
* void
* @param q
* @param s
* @param ap
* description:分裂结点
*/
private void split(BSTNode q, int s, BSTNode ap) {
ap.setChilds(new LinkedList<BSTNode>());
ap.setKeys(new LinkedList<Integer>());
ap.getKeys().add(-1);//0号位置不占用
ap.getChilds().add(q.getChilds().get(s));
ap.getChilds().addAll(q.getChilds().subList(s+1, degree+1));
ap.getKeys().addAll(q.getKeys().subList(s+1, degree+1));
ap.setKeynum(degree-s);
q.setKeynum(s-1);
for(int i = degree;i>q.getKeynum();i--){
q.getChilds().removeLast();
q.getKeys().removeLast();
}
for(int i = 0;i<=ap.getKeynum();i++){
if(ap.getChilds().get(i)!=null){
ap.getChilds().get(i).setParent(ap);
}
}
}
/**
* void
* @param q
* @param i
* @param x
* @param ap
* description:插入关键字
*/
private void insert(BSTNode q, int i, int x, BSTNode ap) {
q.getChilds().add(i+1, ap);
q.getKeys().add(i+1,x);
if(ap != null){
ap.setParent(q);
}
q.setKeynum(q.getKeynum()+1);
}
/**
* boolean
* @param bt
* @param key
* @return
* description:删除关键字
*/
public boolean deleteKey(int key){
//先查找树中是否有关键字
Result result = searchTree(root, key);
if(result.isTag()){
return deleteTree(result);
}else{
return false;
}
}
public boolean deleteTree(Result result){
/*
* 若删除关键字未非终端结点中的Ki,则可以指针Ai所指子树中的最小关键字
* Y代替Ki
*/
BSTNode q = result.getPtr();
Result minResult = null;
int i= 0;
BSTNode node = null;
if(q.getChilds().get(result.getI()) != null){
minResult = searchMinKey(q.getChilds().get(result.getI())); // 所以,delete()方法删除的都是终端结点
}
if(minResult != null){
node = minResult.getPtr();
i = minResult.getI();
}else{
node = result.getPtr();
i = result.getI();
}
// tmpKeys存储的是整个keys,当node和q的指向是同一个对象的时候,会发生异常
LinkedList<Integer> tmpKeys = new LinkedList<Integer>();
tmpKeys.addAll(node.getKeys());
q.getKeys().remove(result.getI());
q.getKeys().add(result.getI(),tmpKeys.get(i));
return delete(node,i);
}
/**
* boolean
* @param q 待删关键字的结点
* @param i 待删关键字的位置
* @return
* description:
*/
public boolean delete(BSTNode q,int i){
int s,tag = 0;
BSTNode p = null,lc,rc; // p 会指向q的父节点
s = degree%2 == 0 ? degree/2 : (degree/2+1);
int order = -1;
//p = foundParent(q,p,order);
p = q.getParent();
if(p == null){ //根结点
tag = 1;
}else{
order = foundIndexOfParent(q,p);
if(q.getKeynum() >= s){
tag = 2; //直接删除结点
}else{
if(tag == 0 && order < p.getKeynum() && p.getChilds().get(order+1).getKeynum() >= s){
//右兄弟结点关键字个数大于s
tag = 3;
}
if(tag == 0 && order > 0 && p.getChilds().get(order-1).getKeynum() >= s){
//左兄弟结点关键字个数大于s
tag = 4;
}
if(tag == 0 && order < p.getKeynum() && p.getChilds().get(order+1).getKeynum() == s -1){
//右兄弟结点关键字个数等于s-1
tag = 5;
}
if(tag == 0 && order > 0 && p.getChilds().get(order-1).getKeynum() == s - 1){
//左兄弟结点关键字个数等于s -1
tag = 6;
}
}
}
switch(tag){
case 0 : return false;
case 1 : //只有根结点一个结点的情况
removeKeyAndChild(q,i);
if(q.getKeynum() == 1 && i == 1){
root = q.getChilds().get(0);
}
q.setKeynum(q.getKeynum() - 1);
break;
case 2 :
removeKeyAndChild(q,i);
q.setKeynum(q.getKeynum()-1);
break;
case 3 :
rc = p.getChilds().get(order+1);
removeKeyAndChild(q, i);
q.getKeys().add(p.getKeys().get(order+1));
q.getChilds().add(rc.getChilds().get(0));
p.getKeys().remove(order+1);
p.getKeys().add(order+1,rc.getKeys().get(1));
rc.getChilds().remove(0);
rc.getKeys().remove(1);
rc.setKeynum(rc.getKeynum() -1);
break;
case 4 :
lc = p.getChilds().get(order - 1);
removeKeyAndChild(q, i);
q.getChilds().add(0,lc.getChilds().get(lc.getKeynum()));
q.getKeys().add(1,p.getKeys().get(order));
p.getKeys().remove(order);
p.getKeys().add(order,lc.getKeys().get(lc.getKeynum()));
removeKeyAndChild(lc, lc.getKeynum());
lc.setKeynum(lc.getKeynum() - 1);
break;
case 5 :
rc = p.getChilds().get(order + 1);
removeKeyAndChild(q, i);
q.getKeys().add(p.getKeys().get(order + 1));
q.setKeynum(q.getKeynum() + rc.getKeynum());
removeKeyAndChild(p, order+1); // p.getChilds(order) 指向 q,q和rc合并来,所以没有问题
q.getChilds().addAll(rc.getChilds());
q.getKeys().addAll(rc.getKeys().subList(1, rc.getKeys().size()));
p.setKeynum(p.getKeynum() - 1);
if(p.getKeynum() < s - 1){ //构造一个虚假关键字
p.setKeynum(p.getKeynum() + 1);
q = p;
delete(q,q.getKeynum());
}
break;
case 6 :
lc = p.getChilds().get(order - 1);
lc.getKeys().add(p.getKeys().get(order));
lc.setKeynum(lc.getKeynum() + 1);
removeKeyAndChild(q, i);
q.setKeynum(q.getKeynum() - 1);
removeKeyAndChild(p, order);
p.setKeynum(p.getKeynum() - 1);
lc.getChilds().addAll(q.getChilds());
q.getKeys().removeFirst();
lc.getKeys().addAll(q.getKeys());
lc.setKeynum(lc.getKeynum() + q.getKeynum());
if(p.getKeynum() < s - 1){
p.setKeynum(p.getKeynum() + 1);
q = p;
delete(q,q.getKeynum());
}
break;
}
return true;
}
public void removeKeyAndChild(BSTNode q,int i){
if(i > q.getKeys().size()-1){
return ;
}
q.getChilds().remove(i);
q.getKeys().remove(i);
}
public int foundIndexOfParent(BSTNode q,BSTNode p){
int count;
for(count = 0 ;p.getChilds().get(count)!=q;count ++);
return count;
}
/**
* Result
* @param p
* @return
* description:查找最小的结点
*/
public Result searchMinKey(BSTNode p){
while(p!=null && p.getChilds().get(0)!=null){
p = p.getChilds().get(0);
}
return new Result(p, 1, true);
}
//--------------------------------------------
/*
* 打印b-tree树
*/
public void printfTree(BSTNode root,int count){
count ++;
for(int i = 0;i<=root.getKeynum();i++){
if(i == 0){
System.out.println(root.getKeys().toString());
}
if(root.getChilds().get(i) != null){
System.out.print("第"+count+"层第"+i+"个孩子:");
printfTree(root.getChilds().get(i),count);
}
}
}
@Override
public String toString() {
return "BTree [degree=" + degree + ", root=" + root + "]";
}
}
三、测试类
public class Test {
public static void main(String[] args) {
BTree b = new BTree(3,null); //3阶树
b.insertKey(12);
b.insertKey(24);
b.insertKey(37);
b.insertKey(3);
b.insertKey(45);
b.insertKey(50);
System.out.println("删除前:");
b.printfTree(b.getRoot(),0);
b.deleteKey(37);
System.out.println("删除后:");
b.printfTree(b.getRoot(), 0);
}
}
四、打印的结果
删除前:
[-1, 24, 45]
第1层第0个孩子:[-1, 3, 12]
第1层第1个孩子:[-1, 37]
第1层第2个孩子:[-1, 50]
删除后:
[-1, 12, 45]
第1层第0个孩子:[-1, 3]
第1层第1个孩子:[-1, 24]
第1层第2个孩子:[-1, 50]
(注:-1可以忽略,因为keys的0号存储单元不使用,-1没有实际意义)