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 }