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