package tree import ( "data-structures-and-algorithms/contract" "data-structures-and-algorithms/queue" "fmt" "sort" "strings" ) var ( nilItems = make([]interface{}, 16) nilChildren = make([]*btreeNode, 16) ) // b-树节点 // k0 k1 k2 // c0 c1 c2 c3 // 1. len(key) = len(children) - 1 // 2. ci <= ki < ci+1 // 3. 空 btreeNode 无数据信息,包含一个为 nil 的 lc。 type btreeNode struct { parent *btreeNode items []interface{} children []*btreeNode } // 新建空节点 func emptyBtreeNode(parent *btreeNode) *btreeNode { node := &btreeNode{parent: parent} node.children = append(node.children, nil) return node } // 在指定位置插入元素 func (n *btreeNode) insertItemAt(index int, item interface{}) { n.items = append(n.items, nil) if index < len(n.items) { copy(n.items[index+1:], n.items[index:]) } n.items[index] = item } // 在指定位置移除元素 func (n *btreeNode) removeItemAt(index int) interface{} { item := n.items[index] copy(n.items[index:], n.items[index+1:]) n.items[len(n.items)-1] = nil n.items = n.items[:len(n.items)-1] return item } // 在指定位置插入子节点指针 func (n *btreeNode) insertChildAt(index int, child *btreeNode) { n.children = append(n.children, nil) if index < len(n.children) { copy(n.children[index+1:], n.children[index:]) } n.children[index] = child } // 在指定位置删除子节点指针 func (n *btreeNode) removeChildAt(index int) *btreeNode { child := n.children[index] copy(n.children[index:], n.children[index+1:]) n.children[len(n.children)-1] = nil n.children = n.children[:len(n.children)-1] return child } // 截断slice中的元素 func (n *btreeNode) truncateItem(index int) { var toClear []interface{} n.items, toClear = n.items[:index], n.items[index:] for len(toClear) > 0 { toClear = toClear[copy(toClear, nilItems):] } } // 截断slice中子节点指针元素 func (n *btreeNode) truncateChild(index int) { var toClear []*btreeNode n.children, toClear = n.children[:index], n.children[index:] for len(toClear) > 0 { toClear = toClear[copy(toClear, nilChildren):] } } // 节点 n 在位置 index 处进行分裂 func (n *btreeNode) split(index int) (interface{}, *btreeNode) { item := n.items[index] node := &btreeNode{} node.items = append(node.items, n.items[index+1:]...) node.children = append(node.children, n.children[index+1:]...) n.truncateItem(index) n.truncateChild(index + 1) if node.children[0] != nil { for _, child := range node.children { child.parent = node } } return item, node } // 当前节点为其父节点的第几个孩子 func (n *btreeNode) nth() int { var index int for size := len(n.parent.children); index < size; index++ { if n.parent.children[index] == n { break } } return index } // 将节点 n 与其右兄弟以及父节点中 index 位置的元素进进行合并. func (n *btreeNode) merge(index int, rs *btreeNode) *btreeNode { item := n.parent.removeItemAt(index) n.parent.removeChildAt(index + 1) n.insertItemAt(len(n.items), item) n.items = append(n.items, rs.items...) n.children = append(n.children, rs.children...) rs.items = nil rs.children = nil return n } // 在树节点中寻找 item 所在位置:成功时返回 item[i] == key; 失败时 item[i-1] < key < item[i] func (n *btreeNode) find(comparator contract.Comparator, item interface{}) (int, bool) { i := sort.Search(len(n.items), func(i int) bool { return comparator(item, n.items[i]) < 0 }) if i > 0 && comparator(item, n.items[i-1]) == 0 { return i - 1, true } return i, false } // Btree B-树 type Btree struct { hot *btreeNode root *btreeNode size int order int keyComparator contract.Comparator } // 算法: // 1、x != nil 时,在 x 中查找 key 对于位置 i。 // 2.1、x.key[i] == key, return x。 // 2.2、x.key[i] != key, x = x.children[i],执行 1。 func (t *Btree) searchAt(node *btreeNode, item interface{}) (*btreeNode, int) { t.hot = nil for node != nil { i, found := node.find(t.keyComparator, item) if found { return node, i } t.hot = node node = node.children[i] } return nil, 0 } // solveOverflow 上溢修复 // 算法: // 1、节点 x 是否上溢,未上溢则终止。 // 2、节点元素取中 item, 并分裂为两个节点 l, r。处理 l, r 中的 keys 和 children 以及子节点指针。 // 4、在x父节点(父节点不存在时则意味着在根节点溢出,新建根节点)适当位置插入 item,以及新的子节点指针并指向 r。 // 4、令 x 为 x父节点,执行算法 1。 func (t *Btree) solveOverflow(node *btreeNode) { if len(node.children) <= t.order { return } index := t.order >> 1 item, newNode := node.split(index) p := node.parent if p == nil { p = emptyBtreeNode(nil) p.children[0] = node node.parent = p t.root = p } newNode.parent = p r, _ := p.find(t.keyComparator, item) p.insertItemAt(r, item) p.insertChildAt(r+1, newNode) t.solveOverflow(p) } // solveUnderflow 下溢修复 // 算法(左顾右盼+合并): // 1、节点 x 是否下溢,未下溢则终止。 // 2、x 为树根,倘若作为树根的节点已不含关键码,却有(唯一的)非空孩子,则这个节点可被跳过,并因不再有用而被销毁,整树高度降低一层。 // 3、x左兄弟存在且元素充足,从左兄弟转借一个元素。 // 4、x右兄弟存在且元素充足,从右兄弟转借一个元素。 // 5、合并x与左或右兄弟。 func (t *Btree) solveUnderflow(node *btreeNode) { if (t.order+1)>>1 <= len(node.children) { return } p := node.parent if p == nil { if len(node.items) == 0 && node.children[0] != nil { t.root = node.children[0] t.root.parent = nil node.children[0] = nil } return } index := node.nth() if index < len(p.children)-1 && (t.order+1)>>1 < len(p.children[index+1].children) { // 从右孩子借 rs := p.children[index+1] node.insertItemAt(len(node.items), p.items[index]) p.items[index] = rs.removeItemAt(0) child := rs.removeChildAt(0) node.insertChildAt(len(node.children), child) if child != nil { child.parent = node } return } else if index > 0 && (t.order+1)>>1 < len(p.children[index-1].children) { // 从左孩子借 ls := p.children[index-1] node.insertItemAt(0, p.items[index-1]) p.items[index-1] = ls.removeItemAt(len(ls.items) - 1) child := ls.removeChildAt(len(ls.children) - 1) node.insertChildAt(0, child) if child != nil { child.parent = node } return } else if index < len(p.children)-1 { // 与右孩子合并 node.merge(index, p.children[index+1]) } else { // 与左孩子合并 p.children[index-1].merge(index-1, node) } t.solveUnderflow(p) } // NewBtree 初始化空B-树 func NewBtree(order int, cmps ...contract.Comparator) *Btree { cmp := contract.DefaultComparator if len(cmps) > 0 { cmp = cmps[0] } return &Btree{order: order, keyComparator: cmp} } // Size 元素个数 func (t *Btree) Size() int { return t.size } // Height 树高 func (t *Btree) Height() (height int) { if t.root == nil { return -1 } x := t.root for ; x != nil && x.children[0] != nil; height++ { x = x.children[0] } return } // Empty 判空 func (t *Btree) Empty() bool { return t.size <= 0 } // Order 当前阶数 func (t *Btree) Order() int { return t.order } // Clear 清空B-树 func (t *Btree) Clear() int { size := t.size t.hot = nil t.root = nil t.size = 0 return size } // Search 元素查找 func (t *Btree) Search(item interface{}) interface{} { node, i := t.searchAt(t.root, item) if node == nil { return nil } return node.items[i] } // Insert 元素新增: // 算法: // 1、找到元素 x 对于节点,存在则返回。 // 2、令最后访问节点为 x, 在 x 中查找元素适合的插入位置 i, 并将其插入。 // 4、x上溢修复。 func (t *Btree) Insert(item interface{}) { if t.Empty() { t.size++ t.root = emptyBtreeNode(nil) t.root.insertItemAt(0, item) t.root.insertChildAt(1, nil) return } node, i := t.searchAt(t.root, item) if node != nil { node.items[i] = item return } t.size++ node = t.hot i, _ = node.find(t.keyComparator, item) node.insertItemAt(i, item) node.insertChildAt(i+1, nil) t.solveOverflow(node) } // Remove 元素删除: // 算法: // 1、找到元素 x 对于节点。 // 2、若节点 x 不为叶节点,则交换 x 与其后继节点。 // 3、在x中删除对于元素。 // 4、在x下溢修复。 func (t *Btree) Remove(item interface{}) { node, i := t.searchAt(t.root, item) if node == nil { return } t.size-- if node.children[0] != nil { suc := node.children[i+1] for suc.children[0] != nil { suc = suc.children[0] } node.items[i], suc.items[0] = suc.items[0], node.items[i] node, i = suc, 0 } node.removeItemAt(i) node.removeChildAt(i + 1) t.solveUnderflow(node) } // 层序遍历打印当前树中节点信息 func (t *Btree) levelInfo() string { var info []string if t.Empty() { return "[]" } que := queue.New() que.Push(t.root) for !que.Empty() { var tmp string size := que.Size() for ; size > 0; size-- { node := que.Pop().(*btreeNode) tmp += fmt.Sprintf("%v ", node.items) if node.children[0] != nil { for _, child := range node.children { que.Push(child) } } } tmp = strings.TrimRight(tmp, " ") info = append(info, tmp) } return "[" + strings.Join(info, "\n") + "]" }