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