在搞的项目需要实现一颗B + 树 来在原有开源项目的基础上实现新增数据结构的存储。搜索了一圈发现网上没有用go语言写的版本,其他语言的版本也都有或多或少的bug,于是自己实现了一个,测试了一下应该没问题。
package main
import (
"fmt"
)
const M = 4
const INT_MAX = int(^uint(0) >> 1)
const INT_MIN = ^INT_MAX
const LIMIT_M_2 = (M + 1)/2
type Position *BPlusFullNode
type BPlusLeafNode struct {
Next *BPlusFullNode
datas []int
}
//叶子节点应该为Children为空,但leafNode中datas不为空 Next一般不为空
type BPlusFullNode struct {
KeyNum int
Key []int
isLeaf bool
Children []*BPlusFullNode
leafNode *BPlusLeafNode
}
type BPlusTree struct {
keyMax int
root *BPlusFullNode
ptr *BPlusFullNode
}
func MallocNewNode(isLeaf bool) *BPlusFullNode {
var NewNode *BPlusFullNode
if isLeaf == true {
NewLeaf := MallocNewLeaf()
NewNode = &BPlusFullNode{
KeyNum: 0,
Key: make([]int, M + 1), //申请M + 1是因为插入时可能暂时出现节点key大于M 的情况,待后期再分裂处理
isLeaf: isLeaf,
Children: nil,
leafNode: NewLeaf,
}
}else{
NewNode = &BPlusFullNode{
KeyNum: 0,
Key: make([]int, M + 1),
isLeaf: isLeaf,
Children: make([]*BPlusFullNode, M + 1),
leafNode: nil,
}
}
for i,_ := range NewNode.Key{
NewNode.Key[i] = INT_MIN
}
return NewNode
}
func MallocNewLeaf() *BPlusLeafNode{
NewLeaf := BPlusLeafNode{
Next: nil,
datas: make([]int, M + 1),
}
for i,_ := range NewLeaf.datas {
NewLeaf.datas[i] = i
}
return &NewLeaf
}
func(tree *BPlusTree) Initialize() {
/* 根结点 */
T := MallocNewNode(true)
tree.ptr = T
tree.root = T
}
func FindMostLeft(P Position) Position{
var Tmp Position
Tmp = P
if Tmp.isLeaf == true || Tmp == nil{
return Tmp
}else if Tmp.Children[0].isLeaf == true{
return Tmp.Children[0]
}else{
for (Tmp != nil && Tmp.Children[0].isLeaf != true ) {
Tmp = Tmp.Children[0]
}
}
return Tmp.Children[0]
}
func FindMostRight(P Position ) Position{
var Tmp Position
Tmp = P
if Tmp.isLeaf == true || Tmp == nil{
return Tmp
}else if Tmp.Children[Tmp.KeyNum - 1].isLeaf == true{
return Tmp.Children[Tmp.KeyNum - 1]
}else{
for (Tmp != nil && Tmp.Children[Tmp.KeyNum - 1].isLeaf != true ) {
Tmp = Tmp.Children[Tmp.KeyNum - 1]
}
}
return Tmp.Children[Tmp.KeyNum - 1]
}
/* 寻找一个兄弟节点,其存储的关键字未满,若左右都满返回nil */
func FindSibling(Parent Position,i int ) Position{
var Sibling Position
var upperLimit int
upperLimit = M
Sibling = nil
if i == 0{
if Parent.Children[1].KeyNum < upperLimit{
Sibling = Parent.Children[1]
}
} else if (Parent.Children[i - 1].KeyNum < upperLimit){
Sibling = Parent.Children[i - 1]
}else if (i + 1 < Parent.KeyNum && Parent.Children[i + 1].KeyNum < upperLimit){
Sibling = Parent.Children[i + 1]
}
return Sibling
}
/* 查找兄弟节点,其关键字数大于M/2 ;没有返回nil j用来标识是左兄还是右兄*/
func FindSiblingKeyNum_M_2( Parent Position,i int, j *int) Position{
var lowerLimit i