github.com/benz9527/toy-box/algo@v0.0.0-20240221120937-66c0c6bd5abd/tree/b_tree.go (about)

     1  package tree
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  type BTreeNode struct {
     8  	// current number of keys
     9  	N int
    10  	// key values array
    11  	Keys []int
    12  	// child pointers array (插空数量)
    13  	Children []*BTreeNode
    14  	IsLeaf   bool
    15  }
    16  
    17  func (n *BTreeNode) Find(key int) (idx int) {
    18  	idx = 0
    19  	for idx < n.N && n.Keys[idx] < key {
    20  		idx++
    21  	}
    22  	return idx
    23  }
    24  
    25  type BTree struct {
    26  	// 整棵树的 degree,限制 key 的数量
    27  	T    int
    28  	Root *BTreeNode
    29  }
    30  
    31  func NewBTree(t int) *BTree {
    32  	btree := &BTree{T: t}
    33  	// 设置 key 的最大数量为 2T - 1, child nodes 的最大数量为 2T
    34  	root := &BTreeNode{N: 0, IsLeaf: true, Keys: make([]int, 2*t-1), Children: make([]*BTreeNode, 2*t)}
    35  	btree.Root = root
    36  	return btree
    37  }
    38  
    39  func (btree *BTree) Search(n *BTreeNode, key int) *BTreeNode {
    40  	i := 0
    41  	if n == nil {
    42  		return n
    43  	}
    44  
    45  	for ; i < n.N; i++ {
    46  		// 遍历完同一层级的所有key
    47  		if key < n.Keys[i] {
    48  			break
    49  		}
    50  
    51  		if key == n.Keys[i] {
    52  			return n
    53  		}
    54  	}
    55  
    56  	if n.IsLeaf {
    57  		return nil
    58  	} else {
    59  		return btree.Search(n.Children[i], key)
    60  	}
    61  }
    62  
    63  func (btree *BTree) Split(nx *BTreeNode, pos int, ny *BTreeNode) {
    64  	// x node is the upper level node
    65  	// y node is the left part
    66  	// z node is the right part
    67  	// 该新节点,准备接收 y node(处于满状态节点)的 T - 1 个 keys
    68  	z := &BTreeNode{
    69  		N:        btree.T - 1,
    70  		IsLeaf:   ny.IsLeaf,
    71  		Keys:     make([]int, 2*btree.T-1),
    72  		Children: make([]*BTreeNode, 2*btree.T),
    73  	}
    74  	// 把后 T - 1 个 key 数据复制到 z node
    75  	for i := 0; i < btree.T-1; i++ {
    76  		z.Keys[i] = ny.Keys[i+btree.T]
    77  	}
    78  	// 如果是叶子节点,它根本没有 children 能够移动
    79  	if !ny.IsLeaf {
    80  		// y node 如果是非叶子节点,把后 T(也就是一半的)个 children 节点复制到 z node
    81  		for i := 0; i < btree.T; i++ {
    82  			z.Children[i] = ny.Children[i+btree.T]
    83  		}
    84  	}
    85  	// 更新 y node 的 key 数量为 T - 1, 也就是 y node children & keys 还保留着原本的信息
    86  	// 但是更新了现有的 keys 的数量信息,这些被保留的冗余会在之后的 insert 中被覆盖掉
    87  	ny.N = btree.T - 1
    88  
    89  	// x node 准备拥有新的 children nodes,腾挪位置
    90  	for i := nx.N; i >= pos+1; i-- {
    91  		nx.Children[i+1] = nx.Children[i]
    92  	}
    93  	// y node 本身就在 children 里面了,所以只需要把 z node 加入到 children 就行
    94  	nx.Children[pos+1] = z
    95  
    96  	// keys 也要腾挪位置
    97  	for i := nx.N - 1; i >= pos; i-- {
    98  		nx.Keys[i+1] = nx.Keys[i]
    99  	}
   100  	// copy the middle key of y node to this node
   101  	nx.Keys[pos] = ny.Keys[btree.T-1]
   102  	nx.N = nx.N + 1
   103  }
   104  
   105  func (btree *BTree) Insert(key int) {
   106  	// 从 root 插入
   107  	r := btree.Root
   108  	// 检查 root 的 key 数量是否达到最大,达到最大时触发新的 root 选取
   109  	if r.N == 2*btree.T-1 {
   110  		// 已经达到最大,需要选出新的 root, 就是中间值
   111  		s := &BTreeNode{IsLeaf: true, Keys: make([]int, 2*btree.T-1), Children: make([]*BTreeNode, 2*btree.T)}
   112  		// 新的 root
   113  		btree.Root = s
   114  		s.IsLeaf = false
   115  		// 临时指向原本的 root 首节点
   116  		s.Children[0] = r
   117  		// 当前 r 是处于节点的满状态, key 的数量达到最大
   118  		btree.Split(s, 0, r)
   119  		btree.InsertValue(s, key)
   120  	} else {
   121  		btree.InsertValue(r, key)
   122  	}
   123  }
   124  
   125  func (btree *BTree) InsertValue(n *BTreeNode, key int) {
   126  	// initialize index as rightmost element index
   127  	i := n.N - 1
   128  	if n.IsLeaf {
   129  		// 叶子节点的操作
   130  
   131  		// 插入的新值比较小,要不断往前找合适的位置
   132  		// a) finds the location of new key to be inserted
   133  		// b) moves all greater keys to one place ahead
   134  		for ; i >= 0 && key < n.Keys[i]; i-- {
   135  			n.Keys[i+1] = n.Keys[i]
   136  		}
   137  		// 找到合适的位置时就填入值
   138  		n.Keys[i+1] = key
   139  		n.N = n.N + 1
   140  	} else {
   141  		// 非叶子节点的操作
   142  		// 从后往前找位置,但是不腾挪数据先
   143  		// find the child which is going to have the new key
   144  		for ; i >= 0 && key < n.Keys[i]; i-- {
   145  			// 当当前 new key 的值比这里所有的 keys 的值都要小,只能往更小的 child 去插入
   146  		}
   147  		// 找到了合适的 child 位置,(如果 children is full)这个也会是调整后 keys 的新索引
   148  		i++
   149  		temp := n.Children[i]
   150  		// see if the found child is full
   151  		// children 满了就要产生一个 parent node 添加到上一层
   152  		if temp.N == 2*btree.T-1 {
   153  			btree.Split(n, i, temp)
   154  			// after split, the middle key of children[i] goes up and
   155  			// children[i] is split into two. See which of the two
   156  			// is going to have the new key
   157  			if key > n.Keys[i] {
   158  				i++
   159  			}
   160  		}
   161  		btree.InsertValue(n.Children[i], key)
   162  	}
   163  }
   164  
   165  func Show(n *BTreeNode) {
   166  	// 先序遍历
   167  	if n == nil {
   168  		fmt.Println("The node can not be nil!")
   169  		return
   170  	}
   171  
   172  	for i := 0; i < n.N; i++ {
   173  		fmt.Print(n.Keys[i], " ")
   174  	}
   175  
   176  	if !n.IsLeaf {
   177  		for i := 0; i < n.N+1; i++ {
   178  			Show(n.Children[i])
   179  		}
   180  	}
   181  }
   182  
   183  func (btree *BTree) Show() {
   184  	Show(btree.Root)
   185  }
   186  
   187  func PreorderShow(n *BTreeNode) {
   188  	i := 0
   189  	for i = 0; i < n.N; i++ {
   190  		if !n.IsLeaf {
   191  			PreorderShow(n.Children[i])
   192  		}
   193  		fmt.Print(n.Keys[i], " ")
   194  	}
   195  
   196  	if !n.IsLeaf {
   197  		PreorderShow(n.Children[i])
   198  	}
   199  }
   200  
   201  func (btree *BTree) PreorderShow() {
   202  	PreorderShow(btree.Root)
   203  	return
   204  }
   205  
   206  func (btree *BTree) Contain(k int) bool {
   207  	if btree.Search(btree.Root, k) != nil {
   208  		return true
   209  	} else {
   210  		return false
   211  	}
   212  }
   213  
   214  func (btree *BTree) RemoveKey(k int) {
   215  	if btree.Root == nil {
   216  		return
   217  	}
   218  
   219  	btree.Remove(btree.Root, k)
   220  	if btree.Root.N == 0 {
   221  		if btree.Root.IsLeaf {
   222  			btree.Root = nil
   223  		} else {
   224  			btree.Root = btree.Root.Children[0]
   225  		}
   226  	}
   227  }
   228  
   229  func (btree *BTree) Remove(parentNode *BTreeNode, k int) {
   230  	// 执行删除的之前,先要分清楚不同的场景
   231  	// 1。是否为叶子结点
   232  	// 是:
   233  	// 叶子结点的 keys 是否大于 btree properties 中要求的数量至少是 ceiling([t-1]/2)
   234  	// -- 是:可以直接删除
   235  	// -- 否:需要通过 fill/merge 填充该叶子节点的 keys 数量 > ceiling([t-1]/2) 才不会在删除后违反 btree properties \
   236  	// fill 需要 inorder predecessor & inorder successor 来, pred 和 succ 主要是填充叶子节点的 parent node, 而
   237  	// parent node 的 key 是用来填充叶子节点
   238  	// merge 是当 pred & succ 的数量都刚好满足 == ceiling([t-1]/2),不能发生借 key 的行为,那就固定选择一边的 parent key &
   239  	// sibling keys 来合并成为一个大的叶子节点,再执行删除
   240  	// 否:
   241  	// 基本就是要进行借 key 填充的操作或者 merge
   242  	// if the key k is in node x (parent node) and x is an internal node
   243  	// 1) if the child y that precedes k in node x has at least keys, then find the predecessor k0 of k in the sub-tree
   244  	// rooted at y. recursively delete k0, and replace k by k0 in x.(we can find k0 and delete it in a single downward pass)
   245  	// 2) if y has fewer than t keys, then, symmetrically, examine the child z that follows k in node x, if z has at least
   246  	// t keys, then find the successors k0 of k in the subtree rooted at z, recursively delete k0, and replace k by k0 in x.
   247  	// 3) otherwise, if both y and z have only t-1 keys, merge k and all of z into y, so that x losses both k and the pointer to z
   248  	// and y now contains 2t-1 keys. then free z and recursively delete k from y
   249  
   250  	// 在当前节点里找 k
   251  	idx := parentNode.Find(k)
   252  
   253  	// k 在当前节点里找到
   254  	if idx < parentNode.N && parentNode.Keys[idx] == k {
   255  		if parentNode.IsLeaf {
   256  			btree.RemoveFromLeaf(parentNode, idx)
   257  		} else {
   258  			btree.RemoveFromNonLeaf(parentNode, idx)
   259  		}
   260  	} else {
   261  		// k 在当前节点里找不到,就可能要转向 child nodes 里去找
   262  		if parentNode.IsLeaf {
   263  			// 这个直接不用找
   264  			return
   265  		}
   266  
   267  		// the key to be removed is present in the sub-tree rooted with this node
   268  		// the flag indicates whether the key is present in the sub-tree rooted
   269  		// with the last child of this node
   270  		flag := false
   271  		if idx == parentNode.N {
   272  			// 相等说明是最右边的子树,不等就是中间或者最前的子树
   273  			flag = true
   274  		}
   275  
   276  		// if the child where the key is supposed to exist has less that t keys,
   277  		// we fill that child
   278  		if parentNode.Children[idx].N < btree.T {
   279  			// 先调整不符合要求的子树再删除
   280  			// 这里存在 merge 的可能
   281  			btree.Fill(parentNode, idx)
   282  		}
   283  
   284  		// if the last child has been merged, it must have merged with the previous
   285  		// child and so we recurse on the (idx-1)th child.
   286  		// else, we recurse on the (idx)th child which now has at least t keys
   287  		if flag && idx > parentNode.N {
   288  			btree.Remove(parentNode.Children[idx-1], k)
   289  		} else {
   290  			btree.Remove(parentNode.Children[idx], k)
   291  		}
   292  	}
   293  	return
   294  }
   295  
   296  // RemoveFromLeaf remove the key present in idx-th position in this node which is a leaf
   297  func (btree *BTree) RemoveFromLeaf(n *BTreeNode, idx int) {
   298  	// move all the keys after the idx-th pos one place backward
   299  	for i := idx + 1; i < n.N; i++ {
   300  		n.Keys[i-1] = n.Keys[i]
   301  	}
   302  	// reduce the count of keys
   303  	n.N--
   304  	return
   305  }
   306  
   307  // RemoveFromNonLeaf remove the key present in idx-th position in this node which is a leaf
   308  func (btree *BTree) RemoveFromNonLeaf(n *BTreeNode, idx int) {
   309  	k := n.Keys[idx]
   310  
   311  	// if the child that precedes k (children[idx]) has at least t keys,
   312  	// find the predecessor 'pred' of k in the subtree rooted at children[idx].
   313  	// replace k by pred. recursively delete pred in children[idx]
   314  	if n.Children[idx].N >= btree.T {
   315  		pred := btree.GetPred(n, idx)
   316  		n.Keys[idx] = pred
   317  		btree.Remove(n.Children[idx], pred)
   318  	} else if n.Children[idx+1].N >= btree.T {
   319  		// if the child children[idx] has less that t keys, examine children[idx + 1].
   320  		// if children[idx + 1] has at least t keys, find the successor 'succ' of k in
   321  		// the subtree rooted at children[idx + 1]
   322  		// replace k by succ
   323  		// recursively delete succ in children[idx + 1]
   324  		succ := btree.GetSucc(n, idx)
   325  		n.Keys[idx] = succ
   326  		btree.Remove(n.Children[idx+1], succ)
   327  	} else {
   328  		// if both children[idx + 1] and children[idx + 1] has less that t keys, merge k and all of
   329  		// into children[idx]
   330  		// now children[idx] contains 2t - 1 keys
   331  		// free children[idx + 1] and recursively delete k from children[idx]
   332  		btree.Merge(n, idx)
   333  		btree.Remove(n.Children[idx], k)
   334  	}
   335  }
   336  
   337  // GetPred get the predecessor of the key, where the key is present in the idx-th position in the node
   338  func (btree *BTree) GetPred(n *BTreeNode, idx int) int {
   339  	// keep moving to the right most node until we reach a leaf
   340  	cur := n.Children[idx]
   341  	for !cur.IsLeaf {
   342  		cur = cur.Children[cur.N]
   343  	}
   344  	// return the last key of the leaf
   345  	return cur.Keys[cur.N-1]
   346  }
   347  
   348  // GetSucc get the successor of the key, where the key is present in the idx-th position in the node
   349  func (btree *BTree) GetSucc(n *BTreeNode, idx int) int {
   350  	// keep moving the left most node starting from children[idx + 1] until we reach a leaf
   351  	cur := n.Children[idx+1]
   352  	for !cur.IsLeaf {
   353  		cur = cur.Children[0]
   354  	}
   355  	// return the first key of the leaf
   356  	return cur.Keys[0]
   357  }
   358  
   359  // Fill to fill up the child node present in the idx-th position in the children[] array
   360  // if that child has less than T - 1 keys
   361  func (btree *BTree) Fill(parentNode *BTreeNode, idx int) {
   362  	// if the previous children[idx - 1] has more than t - 1 keys, borrow a key
   363  	// from that child
   364  	if idx != 0 && parentNode.Children[idx-1].N >= btree.T {
   365  		btree.BorrowFromPrev(parentNode, idx)
   366  	} else if idx != parentNode.N && parentNode.Children[idx+1].N >= btree.T {
   367  		// if the next children[idx + 1] has more than t - 1 keys, borrow a key
   368  		// from that child
   369  		btree.BorrowFromNext(parentNode, idx)
   370  	} else {
   371  		if idx != parentNode.N {
   372  			btree.Merge(parentNode, idx)
   373  		} else {
   374  			btree.Merge(parentNode, idx)
   375  		}
   376  	}
   377  	return
   378  }
   379  
   380  // BorroweFromPrev to borrow a key from the children[idx - 1]-th node and
   381  // place it in children[idx]-th node
   382  func (btree *BTree) BorrowFromPrev(parentNode *BTreeNode, idx int) {
   383  	deletedChild := parentNode.Children[idx]
   384  	leftSibling := parentNode.Children[idx-1]
   385  
   386  	// the last key from children[idx - 1] goes up to the parent and keys[idx - 1]
   387  	// from parent is inserted as the first key in children[idx].
   388  	// thus, the losses leftSibling one key and deletedChild gains one key
   389  
   390  	// move one step ahead
   391  	// 留出空位,(deleted child)left most 接收 new key from parent & new child from sibling (sibling right most)
   392  	for i := deletedChild.N - 1; i >= 0; i-- {
   393  		deletedChild.Keys[i+1] = deletedChild.Keys[i]
   394  	}
   395  
   396  	if !deletedChild.IsLeaf {
   397  		for i := deletedChild.N; i >= 0; i-- {
   398  			deletedChild.Children[i+1] = deletedChild.Children[i]
   399  		}
   400  	}
   401  
   402  	// setting deletedChild's first key equal to keys[idx - 1] from the current node
   403  	deletedChild.Keys[0] = parentNode.Keys[idx-1]
   404  
   405  	// moving leftSibling's last deletedChild as children[idx]'s first deletedChild
   406  	if !deletedChild.IsLeaf {
   407  		deletedChild.Children[0] = leftSibling.Children[leftSibling.N]
   408  	}
   409  
   410  	// move the key at right most in left sibling to parent
   411  	parentNode.Keys[idx-1] = leftSibling.Keys[leftSibling.N-1]
   412  	deletedChild.N += 1
   413  	leftSibling.N -= 1
   414  	return
   415  }
   416  
   417  // BorrowFromNext to borrow a key from the children[idx + 1]-th node and
   418  // place it in children[idx]-th node
   419  func (btree *BTree) BorrowFromNext(parentNode *BTreeNode, idx int) {
   420  	deletedChild := parentNode.Children[idx]
   421  	rightSibling := parentNode.Children[idx+1]
   422  
   423  	// 留出空位,(deleted child)right most 接收 new key from parent & new child from sibling (sibling left most index)
   424  	deletedChild.Keys[deletedChild.N] = parentNode.Keys[idx]
   425  
   426  	// rightSibling's first deletedChild is inserted as the last deletedChild into children[idx]
   427  	if !deletedChild.IsLeaf {
   428  		deletedChild.Children[deletedChild.N+1] = rightSibling.Children[0]
   429  	}
   430  
   431  	// the first key from rightSibling is inserted into keys[idx]
   432  	parentNode.Keys[idx] = rightSibling.Keys[0]
   433  
   434  	// moving all keys in rightSibling one step behind
   435  	// 往前填补空位
   436  	for i := 1; i < rightSibling.N; i++ {
   437  		rightSibling.Keys[i-1] = rightSibling.Keys[i]
   438  	}
   439  
   440  	// moving the deletedChild pointers one step behind
   441  	if !rightSibling.IsLeaf {
   442  		for i := 1; i <= rightSibling.N; i++ {
   443  			rightSibling.Children[i-1] = rightSibling.Children[i]
   444  		}
   445  	}
   446  
   447  	// increasing and decreasing the key count of children[idx] and children[idx + 1]
   448  	// respectively
   449  	deletedChild.N += 1
   450  	rightSibling.N -= 1
   451  	return
   452  }
   453  
   454  // Merge to merge idx-th child of the node with (idx+1)th child of the node
   455  func (btree *BTree) Merge(parentNode *BTreeNode, idx int) {
   456  	deletedChild := parentNode.Children[idx]
   457  	sibling := parentNode.Children[idx+1]
   458  
   459  	// pulling a key from the current node and inserting it into (t-1)th
   460  	// position of children[idx]
   461  	deletedChild.Keys[btree.T-1] = parentNode.Keys[idx]
   462  
   463  	// copying the keys from children[idx + 1] to children[idx] at the end
   464  	for i := 0; i < sibling.N; i++ {
   465  		deletedChild.Keys[i+btree.T] = sibling.Keys[i]
   466  	}
   467  
   468  	// copying the deletedChild pointers from children[idx + 1] to children[idx]
   469  	if !deletedChild.IsLeaf {
   470  		for i := 0; i <= sibling.N; i++ {
   471  			deletedChild.Children[i+btree.T] = sibling.Children[i]
   472  		}
   473  	}
   474  
   475  	// moving all keys after idx in the current node one step before
   476  	// to fill the gap created by moving keys[idx] to children[idx]
   477  	// moving the deletedChild pointers after (idx + 1) in the current node one step before
   478  	for i := idx + 1; i < parentNode.N; i++ {
   479  		parentNode.Keys[i-1] = parentNode.Keys[i]
   480  	}
   481  
   482  	// moving the deletedChild pointers after (idx+1) in the current node one step before
   483  	for i := idx + 2; i <= parentNode.N; i++ {
   484  		parentNode.Children[i-1] = parentNode.Children[i]
   485  	}
   486  
   487  	// updating the key count of deletedChild and the current node
   488  	deletedChild.N += sibling.N + 1
   489  	parentNode.N--
   490  	return
   491  }