B树中的一些概念

- m/2向上取整
- 通常我们说m阶的B树,是指最多的子节点树;最少3阶,上图4阶
- 根的子节点个数 2 <= M <=m 元素个数 1<= K <=m-1
- 内部子节点个数m/2 <= M <=m 元素个数 m/2-1<= K <=m-1
- 叶子节点 元素个数 m/2-1<= K <=m-1
B+树的限制

- 非叶子节点只存储索引,数据都放在叶子节点中,叶子节点含所有数据
- 所有叶子节点是一个链表
- 非叶子节点的关键字的个数与其子树的个数相同;不像B树,子树的个数总比关键字个数多1个
B+树的优点
- 每次查询稳定,深度相同都会到子节点
- 树叶⼦节点存储了所有数据并且进⾏了排序,并且叶⼦节点之间有指针,可以很好的支持全表扫描,范围查找
- B+树更适合外部存储。由于内节点无 data 域,每个节点能索引的范围更大更精确;非叶子节点都只是索引值,没有实际的数据,这就是B+树在一次IO里面,能读出的索引值更多。从而减少查询时候需要的IO次数!
基本操作
| 函数 | 功能 |
|---|
| Len | 获取长度 |
| Min | 获取最小对象 |
| Max | 获取最大对象 |
| Has | 判断对象是否存在 |
| Get | 获取对象,若不存在返回nil |
| Clone | 返回当前树的一个副本 |
| Delete | 删除指定对象 |
| DeleteMax | 删除最大对象 |
| DeleteMin | 删除最小对象 |
| Clear | 清空树 |
| ReplaceOrInsert | 替换或者插入,如果是已经存在的则返回原始对象 |
迭代器操作
| 函数 | 功能 |
|---|
| Ascend | 升序迭代获取整个树 |
| AscendGreaterOrEqual | 升序获取大于等于[a,+∞) |
| AscendLessThan | 升序获取小于(-∞,b) |
| AscendRange | 升序获取范围[a,b) |
| Descend | 降序迭代获取整个树 |
| DescendGreaterOrEqual | 降序获取大于等于[a,+∞) |
| DescendLessThan | 降序获取小于(-∞,b) |
| DescendRange | 降序获取范围[a,b) |
使用DEMO
import (
"fmt"
"strconv"
"github.com/google/btree"
)
type Book struct {
Code int
Name string
}
func (b *Book) Less(item btree.Item) bool {
if v, ok := item.(*Book); ok {
return b.Code < v.Code
}
fmt.Println("Error: not valid item")
return false
}
func testAddSearch() {
tree := btree.New(3)
for i := 0; i < 100; i++ {
tree.ReplaceOrInsert(&Book{Code: i, Name: "freedom" + strconv.Itoa(i)})
}
tree.DescendRange(&Book{Code: 50}, &Book{Code: 48}, func(a btree.Item) bool {
item := a.(*Book)
fmt.Println(item)
return true
})
tree.Ascend(btree.ItemIterator(func(a btree.Item) bool {
item := a.(*Book)
fmt.Println(item)
return true
}))
tree.Descend(btree.ItemIterator(func(a btree.Item) bool {
item := a.(*Book)
fmt.Println(item)
return true
}))
}
func main() {
testAddSearch()
}