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))
}
}