B树的思路以及go语言实现【算法】
一、定义
B树B-tree,B-树其实就是B树,英文名balanced tree。一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树:
1、根结点至少有两个子女;
2、每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;
3、除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ;
4、所有的叶子结点都位于同一层。
5、B树是搜索树(有序)
二、思路实现
B树设计初衷就是为了查找,所以查找是最简单的,相反插入、删除反而异常繁琐,每次操作都会多次使用查找。这里我这要分析B树中如何插入及删除,。
插入操作,一般搜索树而言,插入就是找到相应的位置,直接加入节点,B树为了数据能够快速被查找,在插入的时候不仅要插入到相应的位置,还需要根据情况来调整树的高度以及宽度,尽可能使树高度下降。
插入分为以下几种:
1、若插入的节点中含有的关键词小于m-1,则正常添加关键词到节点即可
2、若插入的节点中含有关键词等于m-1(这里不存在大于m-1,因为一旦达到m就会分裂),则需要向上分裂(这个是需要递归到根节点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | //r为根节点指针,key为插入关键词,value是插入的数据 func InsertTreeNode(r *node, key int16, value int16) int16 { if r.indexesNum == 0 { // 根节点为空 fmt.Println( "root is empty node" , r) r.indexes = make([]int16, M+1, M+1) r.vals = make([]int16, M+1, M+1) r.children = make([]*node, M+1, M+1) var i int16 for i = 0; i <= M; i++ { r.indexes[0] = 0 r.vals[i] = 0 r.children[i] = nil } r.indexesNum++ r.indexes[1] = key r.vals[1] = value } else { // Find out if this node exists res, pos, state := FindOfNode(r, key) //res是查找到的节点,pos找到插入的位置 if state == TRUE { // 每次查找都需要判断是否存在数据 fmt.Println( "This n node is exist!" ) return ERROR } if state == FALSE { // 不存在关键词,表示可以插入 res.indexesNum++ var i int16 for i = res.indexesNum; i > pos; i-- { res.indexes[i] = res.indexes[i-1] res.children[i] = res.children[i-1] res.vals[i] = res.vals[i-1] } res.indexes[pos] = key res.vals[pos] = value res.children[pos] = nil if res.indexesNum == M { //这里就是达到节点能储存的关键词上线就需要向上分裂 splitEdge(res) } renewParent(r) //每次分裂会导致节点位置变化,需要重新指向父级指针 } } return OK } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | /** Split Nodes<br>向上分裂 */ func splitEdge(n *node) int16 { var n1, n2 *node var i, pos int16 if n.parent == nil { n1 = MakeNode() n2 = MakeNode() n1.indexesNum = M / 2 n2.indexesNum = M - M/2 - 1 n1.parent = n n2.parent = n for i = 0; i <= M; i++ { n1.children[i] = nil n1.indexes[i] = 0 n1.vals[i] = 0 n2.children[i] = nil n2.indexes[i] = 0 n2.vals[i] = 0 } for i = 0; i <= M/2; i++ { n1.children[i] = n.children[i] n1.indexes[i] = n.indexes[i] n1.vals[i] = n.vals[i] } n2.children[0] = n.children[M/2+1] for i = M/2 + 2; i <= M; i++ { n2.children[i-M/2-1] = n.children[i] n2.indexes[i-M/2-1] = n.indexes[i] n2.vals[i] = n.vals[i] } n.indexesNum = 1 n.children[0] = n1 n.children[1] = n2 n.indexes[1] = n.indexes[M/2+1] n.vals[1] = n.vals[M/2+1] for i = 2; i <= M; i++ { n.indexes[i] = 0 n.vals[i] = 0 n.children[i] = nil } } else { pos = WhichChildNode(n) for i = n.parent.indexesNum; i > pos; i-- { n.parent.indexes[i+1] = n.parent.indexes[i] n.parent.vals[i+1] = n.parent.vals[i] n.parent.children[i+1] = n.parent.children[i] } n.parent.indexesNum++ n.parent.indexes[pos+1] = n.indexes[M/2+1] n.parent.vals[pos+1] = n.vals[M/2+1] n2 = MakeNode() n.parent.children[pos+1] = n2 for i = 0; i <= M; i++ { n2.indexes[i] = 0 n2.vals[i] = 0 n2.children[i] = nil } n2.indexesNum = M - M/2 - 1 n2.parent = n.parent n2.children[0] = n.children[M/2+1] for i = M/2 + 2; i <= M; i++ { // Initialization n2 n2.indexes[i-M/2-1] = n.indexes[i] n2.vals[i-M/2-1] = n.vals[i] n2.children[i-M/2-1] = n.children[i] } n.indexesNum = M / 2 for i = M/2 + 1; i <= M; i++ { // Initialization n1 n.indexes[i] = 0 n.vals[i] = 0 n.children[i] = nil } if n.parent.indexesNum == M { splitEdge(n.parent) } } return OK } |
上面插入还算简单,接着就是删除操作,对于删除方式,首先分为叶子跟非叶子节点:
非叶子节点:如果该关键字所在的结点不是最下层的非叶子结点,则先需要把此关键字与它在B树中后继(最近右边子树)对换位置,即以指针Pi所指子树中的最小关键字Y代替Ki,然后在相应的结点中删除Y。
叶子节点:(非叶子节点需要替换到叶子节点,然后在进行下面的操作)
1、若该关键字Ki所在结点中的关键字个数大于等于m/2,则可以直接从该结点中删除该关键字和相应指针即可。(这个最简单)
2、若该关键字Ki所在结点中的关键字个数小于m/2,可以分为以下几种:
1)考虑左兄弟节点中的关键词个数,是否大于等于m/2(这个不需要递归到根节点,因为节点高度没变化)
2)考虑右兄弟节点中的关键词个数,是否大于等于m/2(这个不需要递归到根节点,因为节点高度没变化)
3)兄弟都没多余的关键词个数,那就合并(这个需要递归到根节点)
① 左兄弟(存在的情况)+ 自身(删除后剩余的关键词)+与父级节点中的一个关键词 = 合并到左兄弟节点中
② 右兄弟(存在的情况)+ 自身(删除后剩余的关键词)+与父级节点中的一个关键词 = 合并到自身节点中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | //r为根节点,key为删除的关键词 func DeleteTreeNode(r *node, key int16) int16 { if r == nil { return ERROR } // 找出存在的关键词 res, pos, state := FindOfNode(r, key) if state == FALSE { return FALSE } if state == TRUE { if res.children[0] == nil { // 如果为叶子节点 for i := pos; i < res.indexesNum; i++ { res.indexes[i] = res.indexes[i+1] res.vals[i] = res.vals[i+1] res.children[i] = res.children[i+1] } res.indexesNum-- MergeTreeNode(res) } else { //非叶子节点需要替换后继子节点中最小叶子节点中的最小关键词 rn := FindMinKey(res, res.children[pos], pos) var i int16 for i = 1; i < rn.indexesNum; i++ { rn.indexes[i] = rn.indexes[i+1] rn.vals[i] = rn.vals[i+1] rn.children[i] = rn.children[i+1] } rn.indexesNum-- MergeTreeNode(rn) } renewParent(r) } return ERROR } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /** 合并操作 */ func MergeTreeNode(n *node) int16 { p := n.parent if p == nil || p.indexesNum <= 0 { if n.indexesNum <= 0 { if n.children[0] != nil { root = *n.children[0] } } else { root = *n } root.parent = nil return TRUE } if n.indexesNum >= M/2 { return TRUE } // Borrow it from your brother pos := WhichChildNode(n) // Borrow from brother left var i, j int16 for i = pos - 1; i >= 0; i-- { if p.children[i] != nil && p.children[i].indexesNum > M/2 { // 左兄弟节点有多的关键词 for j = i; j < pos; j++ { MoveLeftToRight(p.children[j], p.children[j+1], p, j+1) } return TRUE } } // Borrow from brother right for i = pos + 1; i <= p.indexesNum; i++ { if p.children[i] != nil && p.children[i].indexesNum > M/2 { // 右兄弟节点有多关键词 for j = i; j > pos; j-- { MoveRightToLeft(p.children[j], p.children[j-1], p, j) } return TRUE } } // 兄弟节点都没多,只能合并 if pos > 0 { // 我向左兄弟合并 if p.children[pos] == nil || p.children[pos-1] == nil { return ERROR } MergeParentBotherLeft(p.children[pos], p.children[pos-1], p, pos) MergeTreeNode(p) // 递归操作 } else if pos < p.indexesNum { // 右兄弟向我合并 if p.children[pos] == nil || p.children[pos+1] == nil { return ERROR } MergeParentBotherRight(p.children[pos+1], p.children[pos], p, pos+1) MergeTreeNode(p) } return TRUE } |
三、总结
起初只是以为B树是简单搜索树的一种,本人也是经常刷水题的程序猿,然而却花费了近一周时间才做出来(我也不知道有没有问题,测试3到10阶),最难的是删除合并,这个思路太卡了,借鉴了各种大神图文讲解,代码研究,终于写出来了。后面有空还会研究B+树、B*树以及其他算法结构。下面附上完整代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 | package gobbk import "fmt" const ( // status NOFIND int16 = -1 OK int16 = 0 TRUE int16 = 1 FALSE int16 = 2 ERROR int16 = 6 // Balanced tree of order M M int16 = 4 nodeMinM = M/2 - 1 nodeMaxM = M - 1 ) type ( node struct { // Number of indexes indexesNum int16 // Do not assign zero indexes []int16 // Custom data values vals []int16 children []*node parent *node } ) // Set a root node var root node func GetRoot() node { return root } // Make a new node func MakeNode() *node { n := node{ indexesNum: 1, indexes: make([]int16, M+1), vals: make([]int16, M+1), children: make([]*node, M+1), parent: nil, } return &n } // Delete this node for the Balanced Tree Node func DeleteTreeNode(r *node, key int16) int16 { if r == nil { return ERROR } // Find out if this node exists res, pos, state := FindOfNode(r, key) if state == FALSE { return FALSE } if state == TRUE { if res.children[0] == nil { // If it's a leaf node for i := pos; i < res.indexesNum; i++ { res.indexes[i] = res.indexes[i+1] res.vals[i] = res.vals[i+1] res.children[i] = res.children[i+1] } res.indexesNum-- MergeTreeNode(res) } else { rn := FindMinKey(res, res.children[pos], pos) var i int16 for i = 1; i < rn.indexesNum; i++ { rn.indexes[i] = rn.indexes[i+1] rn.vals[i] = rn.vals[i+1] rn.children[i] = rn.children[i+1] } rn.indexesNum-- MergeTreeNode(rn) } renewParent(r) } return ERROR } func FindMinKey(n *node, rn *node, pos int16) *node { if n == nil || rn == nil { return nil } if rn.children[0] == nil || rn.children[0].indexesNum == 0 { n1 := MakeNode() n1.indexes[1] = n.indexes[pos] n1.vals[1] = n.vals[pos] n.indexes[pos] = rn.indexes[1] n.vals[pos] = rn.vals[1] rn.indexes[1] = n1.indexes[1] rn.vals[1] = n1.vals[1] return rn } return FindMinKey(n, rn.children[0], pos) } /** Merge Nodes */ func MergeTreeNode(n *node) int16 { p := n.parent if p == nil || p.indexesNum <= 0 { if n.indexesNum <= 0 { if n.children[0] != nil { root = *n.children[0] } } else { root = *n } root.parent = nil return TRUE } if n.indexesNum >= M/2 { return TRUE } // Borrow it from your brother pos := WhichChildNode(n) // Borrow from brother left var i, j int16 for i = pos - 1; i >= 0; i-- { if p.children[i] != nil && p.children[i].indexesNum > M/2 { // The left brother has many nodes for j = i; j < pos; j++ { MoveLeftToRight(p.children[j], p.children[j+1], p, j+1) } return TRUE } } // Borrow from brother right for i = pos + 1; i <= p.indexesNum; i++ { if p.children[i] != nil && p.children[i].indexesNum > M/2 { for j = i; j > pos; j-- { MoveRightToLeft(p.children[j], p.children[j-1], p, j) } return TRUE } } // Borrow node from parent node if pos > 0 { if p.children[pos] == nil || p.children[pos-1] == nil { return ERROR } MergeParentBotherLeft(p.children[pos], p.children[pos-1], p, pos) MergeTreeNode(p) } else if pos < p.indexesNum { if p.children[pos] == nil || p.children[pos+1] == nil { return ERROR } MergeParentBotherRight(p.children[pos+1], p.children[pos], p, pos+1) MergeTreeNode(p) } return TRUE } func MergeParentBotherRight(a *node, b *node, p *node, pos int16) { var i int16 /*------*/ b.indexesNum++ b.indexes[b.indexesNum] = p.indexes[pos] b.vals[b.indexesNum] = p.vals[pos] b.children[b.indexesNum] = a.children[0] /*------*/ for i = pos; i < p.indexesNum; i++ { p.indexes[i] = p.indexes[i+1] p.vals[i] = p.vals[i+1] p.children[i] = p.children[i+1] } p.indexesNum-- /*------*/ for i = 1; i <= a.indexesNum; i++ { b.indexesNum++ b.indexes[b.indexesNum] = a.indexes[i] b.vals[b.indexesNum] = a.vals[i] b.children[b.indexesNum] = a.children[i] } a.indexesNum = 0 } func MergeParentBotherLeft(a *node, b *node, p *node, pos int16) { var i int16 /*------*/ b.indexesNum++ b.indexes[b.indexesNum] = p.indexes[pos] b.vals[b.indexesNum] = p.vals[pos] b.children[b.indexesNum] = a.children[0] /*------*/ for i = pos; i < p.indexesNum; i++ { p.indexes[i] = p.indexes[i+1] p.vals[i] = p.vals[i+1] p.children[i] = p.children[i+1] } p.indexesNum-- /*------*/ for i = 1; i <= a.indexesNum; i++ { b.indexesNum++ b.indexes[b.indexesNum] = a.indexes[i] b.vals[b.indexesNum] = a.vals[i] b.children[b.indexesNum] = a.children[i] } a.indexesNum = 0 } func MoveRightToLeft(a *node, b *node, p *node, pos int16) { var i int16 /*------*/ p.indexesNum++ p.children[p.indexesNum] = p.children[p.indexesNum-1] for i = p.indexesNum; i > pos+1; i-- { p.indexes[i] = p.indexes[i-1] p.vals[i] = p.vals[i-1] p.children[i-1] = p.children[i-2] } /*------*/ p.indexes[pos+1] = a.indexes[1] p.vals[pos+1] = a.vals[1] p.children[pos] = a.children[0] for i = 1; i < a.indexesNum; i++ { a.indexes[i] = a.indexes[i+1] a.vals[i] = a.vals[i+1] a.children[i-1] = a.children[i] } a.children[a.indexesNum-1] = a.children[a.indexesNum] a.indexesNum-- /*------*/ b.indexesNum++ b.indexes[b.indexesNum] = p.indexes[pos] b.vals[b.indexesNum] = p.vals[pos] b.children[b.indexesNum] = p.children[pos] /*------*/ for i = pos; i < p.indexesNum; i++ { p.indexes[i] = p.indexes[i+1] p.vals[i] = p.vals[i+1] p.children[i] = p.children[i+1] } p.indexesNum-- } func MoveLeftToRight(a *node, b *node, p *node, pos int16) { var i int16 /*------*/ p.indexesNum++ for i = p.indexesNum; i > pos; i-- { p.indexes[i] = p.indexes[i-1] p.vals[i] = p.vals[i-1] p.children[i] = p.children[i-1] } /*------*/ p.indexes[pos] = a.indexes[a.indexesNum] p.vals[pos] = a.vals[a.indexesNum] p.children[pos] = a.children[a.indexesNum] a.indexesNum-- /*------*/ b.indexesNum++ for i = b.indexesNum; i > 0; i-- { b.indexes[i] = b.indexes[i-1] b.vals[i] = b.vals[i-1] b.children[i] = b.children[i-1] } b.indexes[1] = p.indexes[pos+1] b.vals[1] = p.vals[pos+1] b.children[0] = p.children[pos] /*------*/ p.children[pos] = p.children[pos+1] for i = pos + 1; i < p.indexesNum; i++ { p.indexes[i] = p.indexes[i+1] p.vals[i] = p.vals[i+1] p.children[i] = p.children[i+1] } p.indexesNum-- } // r为根节点指针,key为插入关键词,value是插入的数据 返回state状态 // Insert a new node for the Balanced Tree Node func InsertTreeNode(r *node, key int16, value int16) int16 { if r.indexesNum == 0 { // The root node is empty fmt.Println( "root is empty node" , r) r.indexes = make([]int16, M+1, M+1) r.vals = make([]int16, M+1, M+1) r.children = make([]*node, M+1, M+1) var i int16 for i = 0; i <= M; i++ { r.indexes[0] = 0 r.vals[i] = 0 r.children[i] = nil } r.indexesNum++ r.indexes[1] = key r.vals[1] = value } else { // Find out if this node exists res, pos, state := FindOfNode(r, key) if state == TRUE { fmt.Println( "This n node is exist!" ) return ERROR } if state == FALSE { res.indexesNum++ var i int16 for i = res.indexesNum; i > pos; i-- { res.indexes[i] = res.indexes[i-1] res.children[i] = res.children[i-1] res.vals[i] = res.vals[i-1] } res.indexes[pos] = key res.vals[pos] = value res.children[pos] = nil if res.indexesNum == M { splitEdge(res) } renewParent(r) } } return OK } /** Split Nodes */ func splitEdge(n *node) int16 { var n1, n2 *node var i, pos int16 if n.parent == nil { n1 = MakeNode() n2 = MakeNode() n1.indexesNum = M / 2 n2.indexesNum = M - M/2 - 1 n1.parent = n n2.parent = n for i = 0; i <= M; i++ { n1.children[i] = nil n1.indexes[i] = 0 n1.vals[i] = 0 n2.children[i] = nil n2.indexes[i] = 0 n2.vals[i] = 0 } for i = 0; i <= M/2; i++ { n1.children[i] = n.children[i] n1.indexes[i] = n.indexes[i] n1.vals[i] = n.vals[i] } n2.children[0] = n.children[M/2+1] for i = M/2 + 2; i <= M; i++ { n2.children[i-M/2-1] = n.children[i] n2.indexes[i-M/2-1] = n.indexes[i] n2.vals[i] = n.vals[i] } n.indexesNum = 1 n.children[0] = n1 n.children[1] = n2 n.indexes[1] = n.indexes[M/2+1] n.vals[1] = n.vals[M/2+1] for i = 2; i <= M; i++ { n.indexes[i] = 0 n.vals[i] = 0 n.children[i] = nil } } else { pos = WhichChildNode(n) for i = n.parent.indexesNum; i > pos; i-- { n.parent.indexes[i+1] = n.parent.indexes[i] n.parent.vals[i+1] = n.parent.vals[i] n.parent.children[i+1] = n.parent.children[i] } n.parent.indexesNum++ n.parent.indexes[pos+1] = n.indexes[M/2+1] n.parent.vals[pos+1] = n.vals[M/2+1] n2 = MakeNode() n.parent.children[pos+1] = n2 for i = 0; i <= M; i++ { n2.indexes[i] = 0 n2.vals[i] = 0 n2.children[i] = nil } n2.indexesNum = M - M/2 - 1 n2.parent = n.parent n2.children[0] = n.children[M/2+1] for i = M/2 + 2; i <= M; i++ { // Initialization n2 n2.indexes[i-M/2-1] = n.indexes[i] n2.vals[i-M/2-1] = n.vals[i] n2.children[i-M/2-1] = n.children[i] } n.indexesNum = M / 2 for i = M/2 + 1; i <= M; i++ { // Initialization n1 n.indexes[i] = 0 n.vals[i] = 0 n.children[i] = nil } if n.parent.indexesNum == M { splitEdge(n.parent) } } return OK } // Renew Parent func renewParent(n *node) int16 { if n == nil { return ERROR } var i int16 for i = 0; i <= n.indexesNum; i++ { if n.children[i] != nil { n.children[i].parent = n renewParent(n.children[i]) } } return TRUE } // Find the number of child nodes it is in func WhichChildNode(n *node) int16 { if n == nil { return 0 } var i int16 for i = 0; i <= n.parent.indexesNum; i++ { if n.parent.children[i] == n { return i } } return 0 } /** Find this position of this node @param r (This is root node) @param k (This is the node keyword to be found) @return res (This is the node found) @return pos (This is the node position found) @return state */ func FindOfNode(r *node, k int16) (res *node, pos int16, state int16) { pos = 0 if r == nil { return res, pos, FALSE } q := r for q != nil { var i int16 = 1 key := q.indexes[i] for i <= q.indexesNum { if k == key { // Find this n node res = q pos = i return res, pos, TRUE } if k > key { if i == q.indexesNum { if q.children[i] == nil { res = q pos = i + 1 return res, pos, FALSE } q = q.children[i] break } i++ key = q.indexes[i] continue } if k < key { if q.children[i-1] == nil { res = q pos = i return res, pos, FALSE } q = q.children[i-1] break } } } return res, pos, ERROR } // Traversing tree nodes in middle order func PrintTreeNode(n *node) { arr := []*node{n} iarr := []int16{1} var preH int16 = 1 index := 0 for index < len(arr) && arr[index] != nil { if iarr[index] != preH { preH = iarr[index] fmt.Println( "" ) } fmt.Print( "[" ) var j int16 for j = 1; j <= arr[index].indexesNum; j++ { fmt.Print( " " , arr[index].indexes[j], " " ) } fmt.Print( "]" ) for j = 0; j <= arr[index].indexesNum; j++ { if arr[index].children[j] == nil { break } arr = append(arr, arr[index].children[j]) iarr = append(iarr, preH+1) } index++ } fmt.Println( "" ) return } func InsertTest() { //40, 80, 30, 50, 90, 25, 35, 44, 46, 55, 82, 85, 93 arr := []int16{50, 30, 80, 20, 40, 60, 90, 10, 25, 35, 44, 55, 85, 93, 82, 46,50} for i := 0; i < len(arr); i++ { InsertTreeNode(&root, arr[i], arr[i]) fmt.Println( " i:" , i, ",insert:" , arr[i]) PrintTreeNode(&root) } } func DeleteTest() { arr := []int16{50, 30, 80, 20, 40, 60, 90, 10, 25, 35, 44, 55, 85, 93, 82, 46} for i := 0; i < len(arr); i++ { DeleteTreeNode(&root, arr[i]) fmt.Println( " i:" , i, ",delete:" , arr[i]) PrintTreeNode(&root) } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!