Groovy实现BTree的构建,插入,删除,查询以及遍历
package com.cqs
import org.springframework.util.Assert
import java.util.concurrent.ConcurrentLinkedQueue
/**
* Created by cqs on 2017/11/25.
*/
class BTree {
private Node root //根节点
private int high //高度
private int degree = 6//树阶
private int elements = 0 //总关键数
BTree() {
root = new Node(true, null)
high = 0
assert degree > 2
}
private def class Node {
int n = 0 //节点包含关键数数量
K[] keys = new K[degree - 1] //关键字数组
def children = new Node[degree] //孩子数组
Node parent = null//父节点
boolean leaf //是否为叶子节点
Node(boolean leaf, Node parent) {
this.parent = parent
this.leaf = leaf
}
//是否节点已经满了
def full() {
return n == maxKeys()
}
// def min() {
// return n == minKeys()
// }
K previous2(int pos) {
if (this.leaf) return null
Assert.isTrue(pos >= 0 && pos < this.n, "${pos} 必须为非负数且小于关键数个数")
Node node = this.children[pos]
while (!node.isLeaf()) {
node = node.children[node.n]
}
return node.keys[node.n - 1]
}
K previous(K key) {
return previous2(this.indexKey(key))
}
//获取后继节点(右子树离key最近的节点)
K successor(K key) {
int pos = this.indexKey(key)
Node node = this.children[pos + 1]
while (!node.isLeaf()) {
node = node.children[0]
}
return node.keys[0]
}
//非根节点中关键字数量下限
def minKeys() {
return (int) (Math.ceil(degree / 2)) - 1
}
//非根节点中关键字数量上限
def maxKeys() {
return degree - 1
}
//节点的关键字数量是否合理
def keyNumLegal() {
boolean result
if (this == root) {
result = this.n <= maxKeys() && (root.isLeaf() || root.n > 0)
} else {
result = this.n >= minKeys() && this.n <= maxKeys()
}
if (!result) {
println "error ${this.n} ${this.minKeys()} ${this.maxKeys()} -- ${getActKeys()}"
assert result
}
return result
}
/**
* 返回非负数:包含key 且结果为key在数组keys的索引
* 返回负数,假定返回结果为index 说明节点中不包含key
* 若this是叶子节点 那么-index-1就是要插入的位置
* 若this是非叶子节点 那么 -index-1 就是孩子节点的索引
* -index-1
* @param key
* @return
*/
int indexKey(K key) {
assert getActKeys() != null
return Arrays.binarySearch(getActKeys(), key)
}
//关键字数组
K[] getActKeys() {
return this.keys[0..<(this.n)]
}
//孩子数组
Node[] getActChildren() {
if (isLeaf()) return []
return this.children[0..this.n]
}
//更新关键字
def update(int idx, K key) {
if (idx >= this.n)
throw new ArrayIndexOutOfBoundsException("${idx}值太大 超出${this.n - 1}")
//println "UPDATE ${idx} ${key} ${this.getActKeys()}"
this.keys[idx] = key
}
//检查关键字是否合法
def checkKeys() {
for (int i = 0; i < getActKeys().length; i++) {
assert getActKeys()[i] != null
}
assert keyNumLegal()
}
//检查子树是否合法
def checkActChildren() {
for (int i = 0; i < getActChildren().length; i++) {
assert getActChildren()[i] != null
}
}
//just delete key
// 不涉及孩子节点
def deleteKey(final int pos) {
assert pos < this.n
while (pos < this.n - 1) {
this.keys[pos] = this.keys[pos + 1]
++pos
}
--this.n
}
//仅仅在指定位置写入关键字
def insertKey(int pos, K key) {
if (key == null) {
throw new IllegalArgumentException("写入的关键字不能为空")
}
if (this.indexKey(key) >= 0) {
throw new IllegalAccessError("${key}已经存在,无法再次插入")
}
int i = this.n - 1
assert pos < degree - 1
//this.checkKeys()
while (i >= pos) {
this.keys[i + 1] = this.keys[i]
--i
}
this.keys[pos] = key
++this.n
// this.checkKeys()
// println "keys个数: ${node.n} 总元素:${this.elements} -----${root.getActKeys()}"
}
//向左移动孩子节点
def lMovieChild(int pos) {
while (pos < this.n) {
this.children[pos] = this.children[pos + 1]
++pos
}
}
//向右移动孩子节点
def rMovieChild(int pos) {
while (pos > 0) {
this.children[pos] = this.children[pos - 1]
--pos
}
}
//this.keys[pos]下沉到左孩子节点 然后右孩子节点最小元素krn代替this.keys[pos] ,右孩子删除krn
def rSiblingBorrow(int pos) {
assert pos < this.n
Node rn = this.children[pos + 1]
Node cn = this.children[pos]
K krn = rn.keys[0]
K knode = this.keys[pos]
if (rn.isLeaf()) {
rn.deleteKey(0)
cn.insertKey(cn.n, knode)
this.update(pos, krn)
} else {
//
Node rs = rn.children[0]
//先移动孩子节点 后删除
rn.lMovieChild(0)
rn.deleteKey(0)
cn.insertKey(cn.n, knode)
cn.children[cn.n] = rs
//更新父节点
cn.children[cn.n].parent = cn
this.update(pos, krn)
}
}
//this.keys[pos]下沉到右孩子节点 然后左孩子节点最小元素kln代替this.keys[pos] ,左孩子删除kln
//"向左兄弟节点借元素"
def lSiblingBorrow(int pos) {
assert pos > 0
Node ln = this.children[pos - 1]
Node cn = this.children[pos]
K kln = ln.keys[ln.n - 1]
//注意更新父节点索引为pos-1 这里要区别rSiblingBorrow
int parentIndex = pos - 1
K knode = this.keys[parentIndex]
if (ln.isLeaf()) {
ln.deleteKey(ln.n - 1)
cn.insertKey(0, knode)
this.update(parentIndex, kln)
} else {
//
Node rs = ln.children[ln.n]
//不用移动ln的孩子节点 删除之后ln元素减一
ln.deleteKey(ln.n - 1)
cn.insertKey(0, knode)
//右移孩子节点
cn.rMovieChild(cn.n)
cn.children[0] = rs
rs.parent = cn
this.update(parentIndex, kln)
}
}
//!!!!
//关键字key + 左右孩子节点合并成新的节点
def mergeSibling(final int pos, K key) {
assert pos >= 0
Node lc = this.children[pos]
Node rc = this.children[pos + 1]
assert lc.n == lc.minKeys()
assert rc.n == rc.minKeys()
// println("BEFORE++++++++++++++++++ ${getActKeys()}")
// this.getActChildren().each { println "${it.getActKeys()}" }
//孩子节点向前移动
int p = pos + 1
while (p < this.n) {
this.children[p] = this.children[p + 1]
++p
}
//删除key
this.deleteKey(pos)
//key合并至lc
lc.keys[lc.minKeys()] = key //将key置于lc节点中
//rc合并至lc
rc.minKeys().times {
lc.keys[1 + lc.minKeys() + it] = rc.keys[it]
}
lc.n = maxKeys()
// println("AFTER +++++++++++++++++++++++++ ${getActKeys()}----------${lc.getActKeys()}")
// this.getActChildren().each { println "${it.getActKeys()}" }
if (!lc.isLeaf()) {
//合并孩子节点
p = lc.minKeys() + 1
(rc.minKeys() + 1).times {
lc.children[p] = rc.children[it]
//更新父节点
rc.children[it].parent = lc
++p
}
}
//
if (root.n == 0) {
root = lc
--high
root.parent = null
}
}
}
//向树种添加key元素 若树中存在那么更新 不存在的话就是新增
def put(K key) {
// println "--------------------INSERT ${key}--------------------"
def idx = root.indexKey(key)
if (idx >= 0) {
root.update(idx, key)
return
}
if (root.full()) {
def oroot = root
// print "------------------oldRoot: ${oroot.getActKeys()}--------------"
root = new Node(false, null)
this.high += 1
root.children[0] = oroot
oroot.parent = root
// println "${oroot.parent.getActKeys()} ------!####################"
splitChild(0, oroot)
// println("###################----root: ${root.getActKeys()}################################")
}
insertNonFull(root, key)
}
//删除元素
def delete(K key) {
int ele = this.elements
delete(root, key)
assert ele == this.elements + 1
println "删除${key}成功"
}
//从node为根的子树种删除元素key
def delete(Node node,final K key) {
node.keyNumLegal()
int pos = node.indexKey(key)
if (pos >= 0) {//1)
if (node.isLeaf()) {
node.deleteKey(pos)
--elements
} else {//2)
Node lc = node.getActChildren()[pos]
Node rc = node.getActChildren()[pos + 1]
if (lc.n > lc.minKeys()) {//2a)
K previous = node.previous(key)
node.update(pos, previous)
delete(lc, previous)
} else if (rc.n > rc.minKeys()) {//2b)
K successor = node.successor(key)
node.update(pos, successor)
delete(rc, successor)
} else {//2c)
//move key from node to new node
// node.getActChildren().each { println "${it.getActKeys()}" }
// println("${node.getActChildren()},${lc.getActKeys()},${rc.getActKeys()}")
// node.getActChildren().each { println " child:${it.getActKeys()}" }
node.mergeSibling(pos, key)
delete(lc, key)
}
}
} else {//3) not exist in node
pos = -pos - 1
if (node.isLeaf()) {
// bdf()
// def i = node.indexKey(key)
// println " ${node.indexKey(key)} --------${pos}! -- ${node.getActKeys()}!!!${key} 不存在,删除失败 ${root.getActKeys()}"
throw new IllegalArgumentException("${pos}! -- ${node.getActKeys()}!!!${key} 不存在,删除失败")
} else {
//找到区间(孩子节点)
Node c = node.children[pos]
if (c.n == c.minKeys()) { //3a)
Node lsibling = pos > 0 ? node.children[pos - 1] : null
Node rsibling = pos < node.n ? node.children[pos + 1] : null
def borrow = {
if (lsibling != null) {//先判断是否能从左兄弟节点接
if (lsibling.n > lsibling.minKeys()) {//
node.lSiblingBorrow(pos)
return true
}
}
if (rsibling != null) {//左兄弟借失败的话再判断是否能从做兄弟节点接
if (rsibling.n > rsibling.minKeys()) {
node.rSiblingBorrow(pos)
return true
}
}
return false
}
//返回true 3a)否则进入3b)
boolean bw = borrow.call()
//检查兄弟节点均包含minKeys()个元素
def checkSiblingMin = {
if (lsibling != null && lsibling.n != lsibling.minKeys()) {
return false
}
if (rsibling != null && rsibling.n != rsibling.minKeys()) {
return false
}
return true
}
def ok = checkSiblingMin.call()
if (!bw && ok) {//3b)不能借到元素
if (lsibling != null) {
int n_pos = pos - 1 //这里要十分注意
node.mergeSibling(n_pos, node.keys[n_pos])
// println c == node.children[n_pos]
//左右孩子合并 原来c节点合并至c的左兄弟节点中 所以要更新"递归删除子树的根节点"
c = node.children[n_pos]
} else if (rsibling != null) {
node.mergeSibling(pos, node.keys[pos])
}
}
}
//递归删除
delete(c, key)
}
}
}
//树中是否包含key 包含返回true 不包含返回false
def contains(K key) {
return containsNode(key) != null
}
//树中是否包含key 元素所在节点 不包含返回null
def containsNode(K key) {
int pos
Node node = root
while ((pos = node.indexKey(key)) < 0 && !node.isLeaf()) {
node = node.children[-pos - 1]
}
return pos >= 0 ? node : null
}
//node没有满的情况下写入key
private def insertNonFull(Node node, K key) {
def pos = node.indexKey(key)
if (pos >= 0) {
node.update(pos, key)
return
}
pos = -pos - 1
assert pos < (this.degree - 1)
assert pos <= node.n
if (node.isLeaf()) {
++this.elements
node.insertKey(pos, key)
return
} else {
Node child = node.children[pos]
assert child.parent != null
// if (child.parent != node) {
// println root
// println root.getActChildren().each { println it.getActKeys() }
// println "${node.getActKeys()} -- ${node.isLeaf()} -- ${key}"
// println "${root.children[0].getActKeys()} -- ${node.isLeaf()} -- ${key}"
// node.getActChildren().each { println it.parent.getActKeys() }
// node.getActChildren().each { println it.getActKeys() }
// println "------------------------------------"
// }
assert child.parent == node
if (child == null) {
assert child != null
}
// println "child: ${child.getActKeys()}"
if (child.full()) {
splitChild(pos, child)
assert node.keys[pos] != null
if (key.compareTo(node.keys[pos]) > 0) {
child = node.children[++pos]
}
}
insertNonFull(child, key)
}
}
/**
*
* @param index 分裂出来的元素组成的新结点 插入的node父节点keys的索引
* @param node 待分裂的节点
* @return
*/
private def splitChild(int index, Node node) {
assert node.n == this.degree - 1
def parent = node.parent
//parent.checkActChildren()
// println "parent: ${parent.getActKeys()} --- ${index}"
Node rn = new Node(node.leaf, parent)
int mid = node.minKeys()
// println "${node.keys} ---- mid ${node.keys[mid]}"
int p = node.n - 1
rn.n = node.n - 1 - mid
while (p > mid) {
rn.keys[p - mid - 1] = node.keys[p]
--p
}
if (!node.isLeaf()) {
p = node.n - 1
while (p >= mid) {
rn.children[p - mid] = node.children[p + 1]
//更新父节点
rn.children[p - mid].parent = rn
--p
}
}
node.n = mid
// this.elements -= 1
parent.insertKey(index, node.keys[mid])
p = parent.n - 1
assert p < parent.maxKeys()
while (p > index) {
parent.children[p + 1] = parent.children[p]
--p
}
parent.children[index + 1] = rn
//上浮
parent.keys[index] = node.keys[mid]
//parent.checkActChildren()
assert rn.parent == parent
assert rn.parent == node.parent
//rn.checkActChildren()
// println "node ${node.getActKeys()} ------r ${rn.getActKeys()} ------------p ${parent.getActKeys()}"
}
//广度优先遍历树
def bdf() {
Queue q = new ConcurrentLinkedQueue<>()
q.add(root)
while (q.size() != 0) {
Node nd = q.poll()
q.addAll(nd.getActChildren())
int level = level(nd)
(level).times { print("---|") }
println "${nd.getActKeys()} ---- ${level} ---${this.high}"
}
}
//节点node在树中的那一层
int level(Node node) {
int th = 0
if (node == null) throw new NullPointerException("节点不能为null")
Node tmp = node
while (tmp.parent != null) {
tmp = tmp.parent
th++
}
assert tmp == root
return th
}
static void main(String[] args) {
1.times {
Set set = new HashSet<>()
// set = new TreeSet<>()
int size = 10 + 90 * (1 + it * it)
def r = new Random()
BTree bt = new BTree<>()
size.times {
int ele = r.nextInt(Math.abs(size * 100 * (it + 1)))
set.add(ele)
bt.put(ele)
}
50.times { print "#" }
print "\t${it + 1}\t -- ${bt.elements}"
50.times { print "#" }
println ""
bt.bdf()
// set = set.descendingSet()
set.each {
// 100.times { print("-") }
// println " DELETE ${it} "
bt.delete(it)
// bt.bdf()
}
assert bt.elements == 0
}
}
}
运行结果: