在搞的项目需要实现一颗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 int
var Sibling Position
Sibling = nil
lowerLimit = LIMIT_M_2
if (i == 0){
if (Parent.Children[1].KeyNum > lowerLimit){
Sibling = Parent.Children[1]
*j = 1
}
}else{
if (Parent.Children[i - 1].KeyNum > lowerLimit){
Sibling = Parent.Children[i - 1]
*j = i - 1
} else if (i + 1 < Parent.KeyNum && Parent.Children[i + 1].KeyNum > lowerLimit){
Sibling = Parent.Children[i + 1]
*j = i + 1
}
}
return Sibling
}
/* 当要对X插入data的时候,i是X在Parent的位置,insertIndex是data要插入的位置,j可由查找得到
当要对Parent插入X节点的时候,posAtParent是要插入的位置,Key和j的值没有用
*/
func(tree *BPlusTree) InsertElement (isData bool,Parent Position, X Position, Key int, posAtParent int , insertIndex int, data int) Position {
var k int
if (isData){
/* 插入data*/
k = X.KeyNum - 1
for (k >= insertIndex){
X.Key[k + 1] = X.Key[k]
X.leafNode.datas[k + 1] = X.leafNode.datas[k]
k--
}
X.Key[insertIndex] = Key
X.leafNode.datas[insertIndex] = data
if (Parent != nil) {
Parent.Key[posAtParent] = X.Key[0] //可能min_key 已发生改变
}
X.KeyNum++
}else{
/* 插入节点 */
/* 对树叶节点进行连接 */
if (X.isLeaf == true){
if (posAtParent > 0){
Parent.Children[posAtParent- 1].leafNode.Next = X
}
X.leafNode.Next = Parent.Children[posAtParent]
//更新叶子指针
if X.Key[0] <= tree.ptr.Key[0]{
tree.ptr = X
}
}
k = Parent.KeyNum - 1
for (k >= posAtParent){ //插入节点时key也要对应的插入
Parent.Children[k + 1] = Parent.Children[k]
Parent.Key[k + 1] = Parent.Key[k]
k--
}
Parent.Key[posAtParent] = X.Key[0]
Parent.Children[posAtParent] = X
Parent.KeyNum++
}
return X
}
/*
两个参数X posAtParent 有些重复 posAtParent可以通过X的最小关键字查找得到
*/
func(tree *BPlusTree) RemoveElement(isData bool,Parent Position ,X Position , posAtParent int, deleteIndex int ) Position {
var k,keyNum int
if (isData){
keyNum = X.KeyNum
/* 删除key */
k = deleteIndex + 1
for (k < keyNum){
X.Key[k - 1] = X.Key[k]
X.leafNode.datas[k - 1] = X.leafNode.datas[k]
k++
}
X.Key[keyNum - 1] = INT_MIN
X.leafNode.datas[keyNum - 1] = INT_MIN
Parent.Key[posAtParent] = X.Key[0]
X.KeyNum--
}else{
/* 删除节点 */
/* 修改树叶节点的链接 */
if (X.isLeaf == true && posAtParent > 0){
Parent.Children[posAtParent - 1].leafNode.Next = Parent.Children[posAtParent + 1]
}
keyNum = Parent.KeyNum
k = posAtParent + 1
for (k < keyNum){
Parent.Children[k - 1] = Parent.Children[k]
Parent.Key[k - 1] = Parent.Key[k]
k++
}
if X.Key[0] == tree.ptr.Key[0]{ // refresh ptr
tree.ptr = Parent.Children[0]
}
Parent.Children[Parent.KeyNum - 1] = nil
Parent.Key[Parent.KeyNum - 1] = INT_MIN
Parent.KeyNum--
}
return X
}
/* Src和Dst是两个相邻的节点,posAtParent是Src在Parent中的位置;
将Src的元素移动到Dst中 ,eNum是移动元素的个数*/
func(tree *BPlusTree) MoveElement(src Position , dst Position , parent Position , posAtParent int,eNum int ) Position {
var TmpKey,data int
var Child Position
var j int
var srcInFront bool
srcInFront = false
if (src.Key[0] < dst.Key[0]) {
srcInFront = true
}
j = 0
/* 节点Src在Dst前面 */
if (srcInFront){
if (src.isLeaf == false){
for (j < eNum) {
Child = src.Children[src.KeyNum - 1]
tree.RemoveElement(false, src, Child, src.KeyNum - 1, INT_MIN) //每删除一个节点keyNum也自动减少1 队尾删
tree.InsertElement(false, dst, Child, INT_MIN, 0, INT_MIN,INT_MIN) //队头加
j++
}
}else{
for (j < eNum) {
TmpKey = src.Key[src.KeyNum -1]
data = src.leafNode.datas[src.KeyNum - 1]
tree.RemoveElement(true, parent, src, posAtParent, src.KeyNum - 1)
tree.InsertElement(true, parent, dst, TmpKey, posAtParent + 1, 0,data)
j++
}
}
parent.Key[posAtParent+ 1] = dst.Key[0]
/* 将树叶节点重新连接 */
if (src.KeyNum > 0) {
FindMostRight(src).leafNode.Next = FindMostLeft(dst) //似乎不需要重连,src的最右本身就是dst最左的上一元素
}else {
if src.isLeaf == true {
parent.Children[posAtParent - 1 ].leafNode.Next = dst
}
// 此种情况肯定是merge merge中有实现先移动再删除操作
//tree.RemoveElement(false ,parent.parent,parent ,parentIndex,INT_MIN )
}
}else{
if (src.isLeaf == false){
for (j < eNum) {
Child = src.Children[0]
tree.RemoveElement(false, src, Child, 0, INT_MIN) //从src的队头删
tree.InsertElement(false, dst, Child, INT_MIN, dst.KeyNum, INT_MIN,INT_MIN)
j++
}
}else{
for (j < eNum) {
TmpKey = src.Key[0]
data = src.leafNode.datas[0]
tree.RemoveElement(true, parent, src, posAtParent, 0)
tree.InsertElement(true, parent, dst, TmpKey, posAtParent - 1, dst.KeyNum,data)
j++
}
}
parent.Key[posAtParent] = src.Key[0]
if (src.KeyNum > 0) {
FindMostRight(dst).leafNode.Next = FindMostLeft(src)
}else {
if src.isLeaf == true {
dst.leafNode.Next = src.leafNode.Next
}
//tree.RemoveElement(false ,parent.parent,parent ,parentIndex,INT_MIN )
}
}
return parent
}
//i为节点X的位置
func(tree *BPlusTree) SplitNode(Parent Position, beSplitedNode Position, i int) Position{
var j,k, keyNum int
var NewNode Position
if beSplitedNode.isLeaf == true {
NewNode = MallocNewNode(true)
}else{
NewNode = MallocNewNode(false)
}
k = 0
j = beSplitedNode.KeyNum / 2
keyNum = beSplitedNode.KeyNum
for (j < keyNum){
if (beSplitedNode.isLeaf == false){ //Internal node
NewNode.Children[k] = beSplitedNode.Children[j]
beSplitedNode.Children[j] = nil
}else {
NewNode.leafNode.datas[k] = beSplitedNode.leafNode.datas[j]
beSplitedNode.leafNode.datas[j] = INT_MIN
}
NewNode.Key[k] = beSplitedNode.Key[j]
beSplitedNode.Key[j] = INT_MIN
NewNode.KeyNum++
beSplitedNode.KeyNum--
j++
k++
}
if (Parent != nil) {
tree.InsertElement(false, Parent, NewNode, INT_MIN, i+1, INT_MIN, INT_MIN)
// parent > limit 时的递归split recurvie中实现
}else{
/* 如果是X是根,那么创建新的根并返回 */
Parent = MallocNewNode(false)
tree.InsertElement(false , Parent, beSplitedNode, INT_MIN, 0, INT_MIN, INT_MIN)
tree.InsertElement(false, Parent, NewNode,INT_MIN, 1, INT_MIN,INT_MIN)
tree.root = Parent
return Parent
}
return beSplitedNode
// 为什么返回一个X一个Parent?
}
/* 合并节点,X少于M/2关键字,S有大于或等于M/2个关键字*/
func(tree * BPlusTree) MergeNode( Parent Position, X Position, S Position, i int) Position{
var Limit int
/* S的关键字数目大于M/2 */
if (S.KeyNum > LIMIT_M_2){
/* 从S中移动一个元素到X中 */
tree.MoveElement(S, X, Parent, i,1)
}else{
/* 将X全部元素移动到S中,并把X删除 */
Limit = X.KeyNum
tree.MoveElement(X,S, Parent, i,Limit) //最多时S恰好MAX MoveElement已考虑了parent.key的索引更新
tree.RemoveElement(false, Parent, X, i, INT_MIN)
}
return Parent
}
func(tree *BPlusTree) RecursiveInsert( beInsertedElement Position, Key int, posAtParent int , Parent Position,data int) (Position, bool){
var InsertIndex,upperLimit int
var Sibling Position
var result bool
result = true
/* 查找分支 */
InsertIndex = 0
for (InsertIndex < beInsertedElement.KeyNum && Key >= beInsertedElement.Key[InsertIndex]){
/* 重复值不插入 */
if (Key == beInsertedElement.Key[InsertIndex]){
return beInsertedElement ,false
}
InsertIndex++
}
//key必须大于被插入节点的最小元素,才能插入到此节点,故需回退一步
if (InsertIndex != 0 && beInsertedElement.isLeaf == false) {
InsertIndex--
}
/* 树叶 */
if (beInsertedElement.isLeaf == true) {
beInsertedElement = tree.InsertElement(true, Parent, beInsertedElement, Key, posAtParent, InsertIndex,data) //返回叶子节点
/* 内部节点 */
}else {
beInsertedElement.Children[InsertIndex],result = tree.RecursiveInsert(beInsertedElement.Children[InsertIndex], Key, InsertIndex, beInsertedElement,data)
//更新parent发生在split时
}
/* 调整节点 */
upperLimit = M
if (beInsertedElement.KeyNum > upperLimit){
/* 根 */
if (Parent == nil){
/* 分裂节点 */
beInsertedElement = tree.SplitNode(Parent, beInsertedElement, posAtParent)
} else{
Sibling = FindSibling(Parent, posAtParent)
if (Sibling != nil){
/* 将T的一个元素(Key或者Child)移动的Sibing中 */
tree.MoveElement(beInsertedElement, Sibling, Parent, posAtParent, 1)
}else{
/* 分裂节点 */
beInsertedElement = tree.SplitNode(Parent, beInsertedElement, posAtParent)
}
}
}
if (Parent != nil) {
Parent.Key[posAtParent] = beInsertedElement.Key[0]
}
return beInsertedElement, result
}
/* 插入 */
func(tree *BPlusTree) Insert( Key int,data int) (Position,bool){
return tree.RecursiveInsert(tree.root, Key, 0, nil, data) //从根节点开始插入
}
func(tree *BPlusTree) RecursiveRemove( beRemovedElement Position, Key int, posAtParent int, Parent Position) (Position, bool){
var deleteIndex int
var Sibling Position
var NeedAdjust bool
var result bool
Sibling = nil
/* 查找分支 TODO查找函数可以在参考这里的代码 或者实现一个递归遍历*/
deleteIndex = 0
for (deleteIndex < beRemovedElement.KeyNum && Key >= beRemovedElement.Key[deleteIndex]){
if (Key == beRemovedElement.Key[deleteIndex]) {
break
}
deleteIndex++
}
if (beRemovedElement.isLeaf == true){
/* 没找到 */
if (Key != beRemovedElement.Key[deleteIndex] || deleteIndex == beRemovedElement.KeyNum) {
return beRemovedElement, false
}
}else {
if (deleteIndex == beRemovedElement.KeyNum || Key < beRemovedElement.Key[deleteIndex]) {
deleteIndex-- //准备到下层节点查找
}
}
/* 树叶 */
if (beRemovedElement.isLeaf == true){
beRemovedElement = tree.RemoveElement(true, Parent, beRemovedElement, posAtParent, deleteIndex)
}else{
beRemovedElement.Children[deleteIndex],result = tree.RecursiveRemove(beRemovedElement.Children[deleteIndex], Key, deleteIndex, beRemovedElement)
}
NeedAdjust = false
//有子节点的root节点,当keyNum小于2时
if (Parent == nil && beRemovedElement.isLeaf == false && beRemovedElement.KeyNum < 2){
NeedAdjust = true
} else if (Parent != nil && beRemovedElement.isLeaf == false && beRemovedElement.KeyNum < LIMIT_M_2){
/* 除根外,所有中间节点的儿子数不在[M/2]到M之间时。(符号[]表示向上取整) */
NeedAdjust = true
} else if (Parent != nil && beRemovedElement.isLeaf == true && beRemovedElement.KeyNum < LIMIT_M_2){
/* (非根)树叶中关键字的个数不在[M/2]到M之间时 */
NeedAdjust = true
}
/* 调整节点 */
if (NeedAdjust){
/* 根 */
if (Parent == nil){
if(beRemovedElement.isLeaf == false && beRemovedElement.KeyNum < 2){
//树根的更新操作 树高度减一
beRemovedElement = beRemovedElement.Children[0]
tree.root = beRemovedElement.Children[0]
return beRemovedElement,true
}
}else{
/* 查找兄弟节点,其关键字数目大于M/2 */
Sibling = FindSiblingKeyNum_M_2(Parent, posAtParent,&deleteIndex)
if (Sibling != nil){
tree.MoveElement(Sibling, beRemovedElement, Parent, deleteIndex, 1)
}else{
if (posAtParent == 0){
Sibling = Parent.Children[1]
} else{
Sibling = Parent.Children[posAtParent- 1]
}
Parent = tree.MergeNode(Parent, beRemovedElement, Sibling, posAtParent)
//Merge中已考虑空节点的删除
beRemovedElement = Parent.Children[posAtParent]
}
}
}
return beRemovedElement ,result
}
/* 删除 */
func(tree *BPlusTree) Remove(Key int) (Position,bool){
return tree.RecursiveRemove(tree.root, Key, 0, nil)
}
func(tree *BPlusTree) FindData(key int) (int, bool) {
var currentNode *BPlusFullNode
var index int
currentNode = tree.root
for index < currentNode.KeyNum {
index = 0
for key >= currentNode.Key[index] && index < currentNode.KeyNum{
index ++
}
if index == 0 {
return INT_MIN, false
}else{
index--
if currentNode.isLeaf == false {
currentNode = currentNode.Children[index]
}else{
if key == currentNode.Key[index] {
return currentNode.leafNode.datas[index], true
}else{
return INT_MIN, false
}
}
}
}
return INT_MIN, false
}
func main (){
var tree BPlusTree
(&tree).Initialize()
var i int
i = 1
for i < 100 {
_ ,result := tree.Insert(i,i * 10)
fmt.Print(i)
if result == false {
print("数据已存在")
}
i++
}
tree.Remove(7)
tree.Remove(6)
tree.Remove(5)
resultDate,success:=tree.FindData(5)
if success == true {
fmt.Print(resultDate)
fmt.Printf("\n")
}
//遍历结点元素
i = 0
for i < tree.root.Children[1].KeyNum{
fmt.Println(tree.root.Children[1].leafNode.datas[i])
i++
}
}