354
354
# # done whether the iterm
355
355
# # is already in the tree, so insertion of a new item always succeeds.
356
356
357
+
357
358
function Base. insert! (t:: BalancedTree23{K,D,Ord} , k, d, allowdups:: Bool ) where {K,D,Ord <: Ordering }
358
359
359
360
# # First we find the greatest data node that is <= k.
@@ -395,134 +396,122 @@ function Base.insert!(t::BalancedTree23{K,D,Ord}, k, d, allowdups::Bool) where {
395
396
# # go back and fix the parent.
396
397
397
398
newind = push_or_reuse! (t. data, t. freedatainds, KDRec {K,D} (0 ,k,d))
399
+ push! (t. useddatacells, newind)
398
400
p1 = parent
399
- oldchild = leafind
400
401
newchild = newind
401
402
minkeynewchild = k
402
403
splitroot = false
403
404
curdepth = depth
405
+ existingchild = leafind
404
406
407
+
405
408
# # This loop ascends the tree (i.e., follows the path from a leaf to the root)
406
409
# # starting from the parent p1 of
407
- # # where the new key k would go. For each 3-node we encounter
410
+ # # where the new key k will go.
411
+ # # Variables updated by the loop:
412
+ # # p1: parent of where the new node goes
413
+ # # newchild: index of the child to be inserted
414
+ # # minkeynewchild: the minimum key in the subtree rooted at newchild
415
+ # # existingchild: a child of p1; the newchild must
416
+ # # be inserted in the slot to the right of existingchild
417
+ # # curdepth: depth of newchild
418
+ # # For each 3-node we encounter
408
419
# # during the ascent, we add a new child, which requires splitting
409
420
# # the 3-node into two 2-nodes. Then we keep going until we hit the root.
410
421
# # If we encounter a 2-node, then the ascent can stop; we can
411
- # # change the 2-node to a 3-node with the new child. Invariants
412
- # # during this loop are:
413
- # # p1: the parent node (a tree node index) where the insertion must occur
414
- # # oldchild,newchild: the two children of the parent node; oldchild
415
- # # was already in the tree; newchild was just added to it.
416
- # # minkeynewchild: This is the key that is the minimum value in
417
- # # the subtree rooted at newchild.
418
-
419
- while t. tree[p1]. child3 > 0
420
- isleaf = (curdepth == depth)
421
- oldtreenode = t. tree[p1]
422
-
423
- # # Node p1 index a 3-node. There are three cases for how to
424
- # # insert new child. All three cases involve splitting the
425
- # # existing node (oldtreenode, numbered p1) into
426
- # # two new nodes. One keeps the index p1; the other has
427
- # # has a new index called newparentnum.
428
-
429
-
430
- cmp = isleaf ? cmp3_leaf (ord, oldtreenode, minkeynewchild) :
431
- cmp3_nonleaf (ord, oldtreenode, minkeynewchild)
432
-
433
- if cmp == 1
434
- lefttreenodenew = TreeNode {K} (oldtreenode. child1, newchild, 0 ,
435
- oldtreenode. parent,
436
- minkeynewchild, minkeynewchild)
437
- righttreenodenew = TreeNode {K} (oldtreenode. child2, oldtreenode. child3, 0 ,
438
- oldtreenode. parent, oldtreenode. splitkey2,
439
- oldtreenode. splitkey2)
440
- minkeynewchild = oldtreenode. splitkey1
441
- whichp = 1
442
- elseif cmp == 2
443
- lefttreenodenew = TreeNode {K} (oldtreenode. child1, oldtreenode. child2, 0 ,
444
- oldtreenode. parent,
445
- oldtreenode. splitkey1, oldtreenode. splitkey1)
446
- righttreenodenew = TreeNode {K} (newchild, oldtreenode. child3, 0 ,
447
- oldtreenode. parent,
448
- oldtreenode. splitkey2, oldtreenode. splitkey2)
449
- whichp = 2
422
+ # # change the 2-node to a 3-node with the new child.
423
+
424
+ while true
425
+
426
+
427
+ # Let newchild1,...newchild4 be the new children of
428
+ # the parent node
429
+ # Initially, take the three children of the existing parent
430
+ # node and set newchild4 to 0.
431
+
432
+ newchild1 = t. tree[p1]. child1
433
+ newchild2 = t. tree[p1]. child2
434
+ minkeychild2 = t. tree[p1]. splitkey1
435
+ newchild3 = t. tree[p1]. child3
436
+ minkeychild3 = t. tree[p1]. splitkey2
437
+ p1parent = t. tree[p1]. parent
438
+ newchild4 = 0
439
+
440
+ # Now figure out which of the 4 children is the new node
441
+ # and insert it into newchild1 ... newchild4
442
+
443
+ if newchild1 == existingchild
444
+ newchild4 = newchild3
445
+ minkeychild4 = minkeychild3
446
+ newchild3 = newchild2
447
+ minkeychild3 = minkeychild2
448
+ newchild2 = newchild
449
+ minkeychild2 = minkeynewchild
450
+ elseif newchild2 == existingchild
451
+ newchild4 = newchild3
452
+ minkeychild4 = minkeychild3
453
+ newchild3 = newchild
454
+ minkeychild3 = minkeynewchild
455
+ elseif newchild3 == existingchild
456
+ newchild4 = newchild
457
+ minkeychild4 = minkeynewchild
450
458
else
451
- lefttreenodenew = TreeNode {K} (oldtreenode. child1, oldtreenode. child2, 0 ,
452
- oldtreenode. parent,
453
- oldtreenode. splitkey1, oldtreenode. splitkey1)
454
- righttreenodenew = TreeNode {K} (oldtreenode. child3, newchild, 0 ,
455
- oldtreenode. parent,
456
- minkeynewchild, minkeynewchild)
457
- minkeynewchild = oldtreenode. splitkey2
458
- whichp = 2
459
+ throw (AssertionError (" Tree structure is corrupted 1" ))
460
+ end
461
+
462
+ # Two cases: either we need to split the tree node
463
+ # if newchild4>0 else we convert a 2-node to a 3-node
464
+ # if newchild4==0
465
+
466
+ if newchild4 == 0
467
+ # Change the parent from a 2-node to a 3-node
468
+ t. tree[p1] = TreeNode {K} (newchild1, newchild2, newchild3,
469
+ p1parent, minkeychild2, minkeychild3)
470
+ if curdepth == depth
471
+ replaceparent! (t. data, newchild, p1)
472
+ else
473
+ replaceparent! (t. tree, newchild, p1)
474
+ end
475
+ break
459
476
end
460
- # Replace p1 with a new 2-node and insert another 2-node at
461
- # index newparentnum.
462
- t. tree[p1] = lefttreenodenew
463
- newparentnum = push_or_reuse! (t. tree, t. freetreeinds, righttreenodenew)
464
- if isleaf
465
- par = (whichp == 1 ) ? p1 : newparentnum
466
- # fix the parent of the new datanode.
467
- replaceparent! (t. data, newind, par)
468
- push! (t. useddatacells, newind)
469
- replaceparent! (t. data, righttreenodenew. child1, newparentnum)
470
- replaceparent! (t. data, righttreenodenew. child2, newparentnum)
477
+ # Split the parent
478
+ t. tree[p1] = TreeNode {K} (newchild1, newchild2, 0 ,
479
+ p1parent, minkeychild2, minkeychild2)
480
+ newtreenode = TreeNode {K} (newchild3, newchild4, 0 ,
481
+ p1parent, minkeychild4, minkeychild2)
482
+ newparentnum = push_or_reuse! (t. tree, t. freetreeinds, newtreenode)
483
+ if curdepth == depth
484
+ replaceparent! (t. data, newchild2, p1)
485
+ replaceparent! (t. data, newchild3, newparentnum)
486
+ replaceparent! (t. data, newchild4, newparentnum)
471
487
else
472
- # If this is not a leaf, we still have to fix the
473
- # parent fields of the two nodes that are now children
474
- # # of the newparent.
475
- replaceparent! (t. tree, righttreenodenew. child1, newparentnum)
476
- replaceparent! (t. tree, righttreenodenew. child2, newparentnum)
488
+ replaceparent! (t. tree, newchild2, p1)
489
+ replaceparent! (t. tree, newchild3, newparentnum)
490
+ replaceparent! (t. tree, newchild4, newparentnum)
477
491
end
478
- oldchild = p1
492
+ # Update the loop variables for the next level of the
493
+ # ascension
494
+ existingchild = p1
479
495
newchild = newparentnum
480
- # # If p1 is the root (i.e., we have encountered only 3-nodes during
481
- # # our ascent of the tree), then the root must be split.
482
- if p1 == t . rootloc
483
- @invariant curdepth == 1
496
+ p1 = p1parent
497
+ minkeynewchild = minkeychild3
498
+ curdepth -= 1
499
+ if curdepth == 0
484
500
splitroot = true
485
501
break
486
502
end
487
- p1 = t. tree[oldchild]. parent
488
- curdepth -= 1
489
503
end
490
504
491
- # # big loop terminated either because a 2-node was reached
492
- # # (splitroot == false) or we went up the whole tree seeing
493
- # # only 3-nodes (splitroot == true).
494
- if ! splitroot
495
-
496
- # # If our ascent reached a 2-node, then we convert it to
497
- # # a 3-node by giving it a child3 field that is >0.
498
- # # Encountering a 2-node halts the ascent up the tree.
499
-
500
- isleaf = curdepth == depth
501
- oldtreenode = t. tree[p1]
502
- cmpres = isleaf ? cmp2_leaf (ord, oldtreenode, minkeynewchild) :
503
- cmp2_nonleaf (ord, oldtreenode, minkeynewchild)
504
-
505
-
506
- t. tree[p1] = cmpres == 1 ?
507
- TreeNode {K} (oldtreenode. child1, newchild, oldtreenode. child2,
508
- oldtreenode. parent,
509
- minkeynewchild, oldtreenode. splitkey1) :
510
- TreeNode {K} (oldtreenode. child1, oldtreenode. child2, newchild,
511
- oldtreenode. parent,
512
- oldtreenode. splitkey1, minkeynewchild)
513
- if isleaf
514
- replaceparent! (t. data, newind, p1)
515
- push! (t. useddatacells, newind)
516
- end
517
- else
518
- # # Splitroot is set if the ascent of the tree encountered only 3-nodes.
519
- # # In this case, the root itself was replaced by two nodes, so we need
520
- # # a new root above those two.
505
+ # If the root has been split, then we need to add a level
506
+ # to the tree that is the parent of the old root and the new node.
521
507
522
- newroot = TreeNode {K} (oldchild, newchild, 0 , 0 ,
523
- minkeynewchild, minkeynewchild)
508
+ if splitroot
509
+ @invariant existingchild == t. rootloc
510
+ newroot = TreeNode {K} (existingchild, newchild, 0 ,
511
+ 0 , minkeynewchild, minkeynewchild)
512
+
524
513
newrootloc = push_or_reuse! (t. tree, t. freetreeinds, newroot)
525
- replaceparent! (t. tree, oldchild , newrootloc)
514
+ replaceparent! (t. tree, existingchild , newrootloc)
526
515
replaceparent! (t. tree, newchild, newrootloc)
527
516
t. rootloc = newrootloc
528
517
t. depth += 1
615
604
# #, 1 if i2 precedes i1.
616
605
617
606
function compareInd (t:: BalancedTree23 , i1:: Int , i2:: Int )
618
- @assert (i1 in t. useddatacells && i2 in t. useddatacells)
607
+ @invariant (i1 in t. useddatacells && i2 in t. useddatacells)
619
608
if i1 == i2
620
609
return 0
621
610
end
@@ -624,6 +613,7 @@ function compareInd(t::BalancedTree23, i1::Int, i2::Int)
624
613
p1 = t. data[i1]. parent
625
614
p2 = t. data[i2]. parent
626
615
@invariant_support_statement curdepth = t. depth
616
+ curdepth = t. depth
627
617
while true
628
618
@invariant curdepth > 0
629
619
if p1 == p2
@@ -647,6 +637,7 @@ function compareInd(t::BalancedTree23, i1::Int, i2::Int)
647
637
p1 = t. tree[i1a]. parent
648
638
p2 = t. tree[i2a]. parent
649
639
@invariant_support_statement curdepth -= 1
640
+ curdepth -= 1
650
641
end
651
642
end
652
643
0 commit comments