go 语言版 B + 树

在搞的项目需要实现一颗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++
        }
    }
    
    

    原文作者:B树
    原文地址: https://blog.csdn.net/m0_37560200/article/details/80452623
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞