B-tree

package main

import (
    "fmt"
    "math/rand"
    "time"
)

//B树的节点
type BtreeNode struct {
    Leaf     bool         //是否叶子
    N        int          //分支的数量
    keys     []int        //存储数据
    Children []*BtreeNode //指向自己的多个分支节点

}

//新建一个节点
func NewBtreeNode(n int, branch int, leaf bool) *BtreeNode {
    return &BtreeNode{leaf,
        n,
        make([]int, branch*2-1), //n个brach对应2n,root  2n-1
        make([]*BtreeNode, branch*2)}
}

//搜索B树枝的节点
func (btreenode *BtreeNode) Search(key int) (mynode *BtreeNode, idx int) {
    i := 0
    //找到合适的位置,找到最后一个小于key的,i之后的就是大于等于
    for i < btreenode.N && btreenode.keys[i] < key {
        i += 1
    }
    if i < btreenode.N && btreenode.keys[i] == key {
        mynode, idx = btreenode, i //找到
    } else if btreenode.Leaf == false {
        //进入孩子叶子继续搜索
        mynode, idx = btreenode.Children[i].Search(key)
    }
    return
}
func (parent *BtreeNode) Split(branch int, idx int) {
    full := parent.Children[idx]                         //孩子节点
    newnode := NewBtreeNode(branch-1, branch, full.Leaf) //新建一个节点,备份
    for i := 0; i < branch-1; i++ {
        newnode.keys[i] = full.keys[i+branch] //数据移动,跳过一个分支
        newnode.Children[i] = full.Children[i+branch]
    }
    newnode.Children[branch-1] = full.Children[branch*2-1] //处理最后
    full.N = branch - 1
    //x新增一个key到children
    for i := parent.N; i > idx; i-- {
        parent.Children[i] = parent.Children[i-1]
        parent.keys[i+1] = parent.keys[i] //从后往前移动
    }
    parent.keys[idx] = full.keys[branch-1]
    parent.Children[idx+1] = newnode //插入数据,增加总量
    parent.N++

}

//节点插入数据
func (btreenode *BtreeNode) InsertNonFull(branch int, key int) {
    if btreenode == nil {
        return
    }
    i := btreenode.N    //记录叶子节点的总量
    if btreenode.Leaf { //是叶子或者不是
        for i > 0 && key < btreenode.keys[i-1] {
            btreenode.keys[i] = btreenode.keys[i-1] //从后往前移动,
            i--                                     //i从后往前移动
        }
        btreenode.keys[i] = key //插入数据
        btreenode.N++           //总量加一

    } else {
        for i > 0 && key < btreenode.keys[i-1] {
            i-- //i从后往前移动
        }
        c := btreenode.Children[i] //找到下标
        if c != nil && c.N == 2*branch-1 {
            btreenode.Split(branch, i) //切割
            if key > btreenode.keys[i] {
                i++
            }
        }
        btreenode.Children[i].InsertNonFull(branch, key) //递归插入孩子叶子

    }

}

//节点显示为字符串
func (btreenode *BtreeNode) String() string {
    return fmt.Sprintf("{n=%d,leaf=%v,Children=%v}\n", btreenode.N, btreenode.keys, btreenode.Children)
}

//B树
type Btree struct {
    Root   *BtreeNode //根节点
    branch int        //分支的数量
}

//插入
func (tree *Btree) Insert(key int) {
    root := tree.Root //根节点
    if root.N == 2*tree.branch-1 {
        s := NewBtreeNode(0, tree.branch, false)
        tree.Root = s //新建一个节点备份根节点
        s.Children[0] = root
        s.Split(tree.branch, 0) //拆分整合
        root.InsertNonFull(tree.branch, key)
    } else {
        root.InsertNonFull(tree.branch, key)
    }
}

//查找
func (tree *Btree) Search(key int) (n *BtreeNode, idx int) {
    return tree.Root.Search(key)
}

//返回字符串
func (tree *Btree) String() string {

    return tree.Root.String() //返回树的字符串
}

//新建B树
func NewBtree(branch int) *Btree {
    return &Btree{NewBtreeNode(0, branch, true), branch}
}

func main() {
    mybtree := NewBtree(100000)
    for i := 100000; i > 0; i-- {
        mybtree.Insert(rand.Int() % 100000)
    }
    fmt.Println(mybtree.String())
    for i := 0; i < 10000; i++ {
        starttime := time.Now()
        fmt.Println(mybtree.Search(i))
        fmt.Println("一共用了", time.Since(starttime))
    }

}

 

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