B+tree

package main

import "fmt"

type BPlustree map[int]node //定义

func NewBplusTree() *BPlustree {
    bt := BPlustree{}               //初始化
    leaf := NewLeafNode(nil)        //叶子节点
    r := NewinteriorNode(nil, leaf) //中间节点
    leaf.parent = r                 //设定父亲节点
    bt[-1] = r                      //根节点
    bt[0] = leaf
    return &bt
}

//返回根节点
func (bpt *BPlustree) Root() node {
    return (*bpt)[-1]
}

//处理第一个节点
func (bpt *BPlustree) First() node {
    return (*bpt)[0]
}

//统计数量
func (bpt *BPlustree) Count() int {
    count := 0
    leaf := (*bpt)[0].(*LeafNode)
    for {
        count += leaf.CountNum() //数量叠加
        if leaf.next == nil {
            break
        }
        leaf = leaf.next
    }
    return count
}

func (bpt *BPlustree) Values() []*LeafNode {
    nodes := make([]*LeafNode, 0) //开辟节点
    leaf := (*bpt)[0].(*LeafNode)
    for {
        nodes = append(nodes, leaf) //数据节点叠加
        if leaf.next == nil {
            break
        }
        leaf = leaf.next
    }
    return nodes
}

//查找数据
func (bpt *BPlustree) Search(key int) (string, bool) {
    kv, _, _ := search((*bpt)[-1], key) //查找
    if kv == nil {
        return "", false
    } else {
        return kv.value, true
    }
}

//搜索数据
func search(n node, key int) (*kv, int, *LeafNode) {
    curr := n
    oldindex := -1
    for {
        switch t := curr.(type) {
        case *LeafNode: //叶子节点搜索
            i, ok := t.find(key)
            if !ok {
                return nil, oldindex, t
            } else {
                return &t.kvs[i], oldindex, t
            }
        case *interiorNode:
            i, _ := t.find(key) //中间节点查找
            curr = t.kcs[i].child
            oldindex = i
        default:
            panic("异常节点")
        }
    }

}

//    1   6
//12345  6789

func (bpt *BPlustree) Insert(key int, value string) {
    //插入之前,确定插入的位置
    _, oldindex, leaf := search((*bpt)[-1], key)
    p := leaf.Parent() //保存父亲节点
    //插入叶子节点,判断是否分裂
    mid, nextleaf, bump := leaf.insert(key, value)
    if !bump { //没有分裂,直接返回
        return
    }
    //f分裂的节点插入B+树
    (*bpt)[mid] = nextleaf
    //中间节点
    var midnode node
    midnode = leaf
    p.kcs[oldindex].child = leaf.next    //设置父亲节点
    leaf.next.SetParent(p)               //分裂的节点设置父亲节点
    interior, interiorP := p, p.Parent() //获取中间点解,父亲节点

    //平衡过程,迭代向上判断,是否需要平衡
    for {
        var oldindex int              //保存老的索引
        var newinterior *interiorNode //新的节点
        //判断是否到达根节点
        isRoot := interiorP == nil
        if !isRoot {
            oldindex, _ = interiorP.find(key) //查找
        }
        //叶子节点分裂后的中间节点传入父亲的中间节点,传入分裂
        mid, newinterior, bump = interior.insert(mid, midnode)
        if !bump {
            return
        }
        (*bpt)[newinterior.kcs[0].key] = newinterior //插入填充好了map
        if !isRoot {
            interiorP.kcs[oldindex].child = newinterior //没有到大根节点,直接插入父亲节点
            newinterior.SetParent(interiorP)
            midnode = interior

        } else {
            //更新节点
            (*bpt)[interior.kcs[0].key] = (*bpt)[-1]       //备份根节点
            (*bpt)[-1] = NewinteriorNode(nil, newinterior) //根节点插入新的根节点
            node := (*bpt)[-1].(*interiorNode)
            node.insert(mid, interior) //重新插入
            (*bpt)[-1] = node
            newinterior.SetParent(node) //设定父亲节点

        }
        interior, interiorP = interiorP, interior.Parent()

    }

}

func main() {
    bpt := NewBplusTree()
    for i := 0; i < 250000; i++ {
        bpt.Insert(i, "x")
    }
    fmt.Println(bpt.Count())
    fmt.Println(bpt.Search(3))
}

 

posted @ 2024-07-20 02:52  爱跑步的乌龟  阅读(3)  评论(0编辑  收藏  举报