Name
Tree::Bulk - Bulk Tree operations
Synopsis
Bulk trees store several (key,data) pairs in each node of a balanced tree to reduce the number of tree pointers: up, left, right, etc. used to maintain the tree. This has no useful effect in Perl code, but in C code, especially C code that uses SIMD instructions, the savings in space can be considerable which allows the processor caches to be used more effectively. This module demonstrates insert, find, delete operations on bulk trees as a basis for coding these algorithms more efficiently in assembler code.
is_deeply $t->printKeys, <<END;
SA0 4 1 2 3 4
Lz2 1 5 6 7 8->9 10 11 12
Rd1 3 9 10 11 12->1 2 3 4
Lz3 1 13 14 15 16->17 18 19 20
Rd2 2 17 18 19 20->9 10 11 12
Rz3 1 21 22->17 18 19 20
END
for my $n($t->inorder)
{$n->setKeysPerNode(2);
}
is_deeply $t->printKeys, <<END;
SA0 5 1 2
Lz3 1 3 4->5 6
Ld2 2 5 6->9 10
Rz3 1 7 8->5 6
Rd1 4 9 10->1 2
Lz4 1 11 12->13 14
Ld3 2 13 14->17 18
Rz4 1 15 16->13 14
Rd2 3 17 18->9 10
Rr3 2 19 20->17 18
Rz4 1 21 22->19 20
END
Description
Bulk Tree operations
Version "20240415".
The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.
Bulk Tree
Bulk Tree
isRoot ($tree)
Return the tree if it is the root
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Attributes";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $b = $t->insert(2,4);
my $a = $t->insert(1,2);
my $c = $t->insert(3,6);
ok $a->isLeftChild;
ok $c->isRightChild;
ok !$a->isRightChild;
ok !$c->isLeftChild;
ok $b->isRoot; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok !$a->isRoot; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok !$c->isRoot; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $a->leaf;
ok $c->leaf;
ok $b->duplex;
ok $c->root == $b;
ok $c->root != $a;
}
root($tree)
Return the root node of a tree
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Attributes";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $b = $t->insert(2,4);
my $a = $t->insert(1,2);
my $c = $t->insert(3,6);
ok $a->isLeftChild;
ok $c->isRightChild;
ok !$a->isRightChild;
ok !$c->isLeftChild;
ok $b->isRoot;
ok !$a->isRoot;
ok !$c->isRoot;
ok $a->leaf;
ok $c->leaf;
ok $b->duplex;
ok $c->root == $b; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $c->root != $a; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
leaf($tree)
Return the tree if it is a leaf
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Attributes";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $b = $t->insert(2,4);
my $a = $t->insert(1,2);
my $c = $t->insert(3,6);
ok $a->isLeftChild;
ok $c->isRightChild;
ok !$a->isRightChild;
ok !$c->isLeftChild;
ok $b->isRoot;
ok !$a->isRoot;
ok !$c->isRoot;
ok $a->leaf; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $c->leaf; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $b->duplex;
ok $c->root == $b;
ok $c->root != $a;
}
duplex ($tree)
Return the tree if it has left and right children
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Attributes";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $b = $t->insert(2,4);
my $a = $t->insert(1,2);
my $c = $t->insert(3,6);
ok $a->isLeftChild;
ok $c->isRightChild;
ok !$a->isRightChild;
ok !$c->isLeftChild;
ok $b->isRoot;
ok !$a->isRoot;
ok !$c->isRoot;
ok $a->leaf;
ok $c->leaf;
ok $b->duplex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $c->root == $b;
ok $c->root != $a;
}
simplex ($tree)
Return the tree if it has either a left child or a right child but not both.
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "SetHeights";
my $a = node(1,1)->setKeysPerNode(1);
my $b = node(2,2)->setKeysPerNode(1);
my $c = node(3,3)->setKeysPerNode(1);
my $d = node(4,4)->setKeysPerNode(1);
my $e = node(5,5);
$a->right = $b; $b->up = $a;
$b->right = $c; $c->up = $b;
$c->right = $d; $d->up = $c;
$d->right = $e; $e->up = $d;
is_deeply $a->printKeys, <<END;
SA0 1 1
Rr1 1 2->1
Rr2 1 3->2
Rr3 1 4->3
Rz4 1 5->4
END
#save $a;
$e->setHeights(1);
is_deeply $a->printKeys, <<END;
SA0 4 1
Rr1 3 2->1
Lz3 1 3->4
Rd2 2 4->2
Rz3 1 5->4
END
#save $a;
ok $b->simplex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok !$c->simplex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$c->balance;
is_deeply $a->printKeys, <<END;
SA0 4 1
Rr1 3 2->1
Lz3 1 3->4
Rd2 2 4->2
Rz3 1 5->4
END
#save $a;
$b->balance;
is_deeply $a->printKeys, <<END;
SA0 4 1
Lr2 2 2->4
Rz3 1 3->2
Rd1 3 4->1
Rz2 1 5->4
END
#save $a;
}
simplexWithLeaf ($tree)
Return the tree if it has either a left child or a right child but not both and the child it has a leaf.
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Balance";
my $a = node(1,1)->setKeysPerNode(1); $a->height = 5;
my $b = node(2,2)->setKeysPerNode(1); $b->height = 4;
my $c = node(3,3)->setKeysPerNode(1); $c->height = 3;
my $d = node(4,4)->setKeysPerNode(1); $d->height = 2;
my $e = node(5,5); $e->height = 1;
$a->right = $b; $b->up = $a;
$b->right = $c; $c->up = $b;
$c->right = $d; $d->up = $c;
$d->right = $e; $e->up = $d;
$e->balance;
is_deeply $a->printKeys, <<END;
SA0 5 1
Rr1 4 2->1
Rr2 3 3->2
Rr3 2 4->3
Rz4 1 5->4
END
#save $a;
ok $d->simplexWithLeaf; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok !$c->simplexWithLeaf; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$d->balance;
is_deeply $a->printKeys, <<END;
SA0 5 1
Rr1 4 2->1
Rr2 3 3->2
Rr3 2 4->3
Rz4 1 5->4
END
#save $a;
$c->balance;
is_deeply $a->printKeys, <<END;
SA0 5 1
Rr1 3 2->1
Lz3 1 3->4
Rd2 2 4->2
Rz3 1 5->4
END
#save $a;
$b->balance;
is_deeply $a->printKeys, <<END;
SA0 4 1
Lr2 2 2->4
Rz3 1 3->2
Rd1 3 4->1
Rz2 1 5->4
END
#save $a;
}
empty ($tree)
Return the tree if it is empty
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Balance";
my $t = Tree::Bulk::new->setKeysPerNode(1);
ok $t->empty; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $t->singleton;
}
singleton ($tree)
Return the tree if it contains only the root node and nothing else
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Balance";
my $t = Tree::Bulk::new->setKeysPerNode(1);
ok $t->empty;
ok $t->singleton; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
isLeftChild ($tree)
Return the tree if it is the left child
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Attributes";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $b = $t->insert(2,4);
my $a = $t->insert(1,2);
my $c = $t->insert(3,6);
ok $a->isLeftChild; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $c->isRightChild;
ok !$a->isRightChild;
ok !$c->isLeftChild; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok $b->isRoot;
ok !$a->isRoot;
ok !$c->isRoot;
ok $a->leaf;
ok $c->leaf;
ok $b->duplex;
ok $c->root == $b;
ok $c->root != $a;
}
isRightChild($tree)
Return the tree if it is the right child
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Attributes";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $b = $t->insert(2,4);
my $a = $t->insert(1,2);
my $c = $t->insert(3,6);
ok $a->isLeftChild;
ok $c->isRightChild; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok !$a->isRightChild; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok !$c->isLeftChild;
ok $b->isRoot;
ok !$a->isRoot;
ok !$c->isRoot;
ok $a->leaf;
ok $c->leaf;
ok $b->duplex;
ok $c->root == $b;
ok $c->root != $a;
}
name($tree)
Name of a tree
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Split and Refill";
my $N = 22;
my $t = Tree::Bulk::new;
for my $k(1..$N)
{$t->insert($k, 2 * $k);
}
is_deeply $t->name, "1 2 3 4"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $t->printKeys, <<END;
SA0 4 1 2 3 4
Lz2 1 5 6 7 8->9 10 11 12
Rd1 3 9 10 11 12->1 2 3 4
Lz3 1 13 14 15 16->17 18 19 20
Rd2 2 17 18 19 20->9 10 11 12
Rz3 1 21 22->17 18 19 20
END
#save $t;
for my $n($t->inorder)
{$n->setKeysPerNode(2);
}
is_deeply $t->printKeys, <<END;
SA0 5 1 2
Lz3 1 3 4->5 6
Ld2 2 5 6->9 10
Rz3 1 7 8->5 6
Rd1 4 9 10->1 2
Lz4 1 11 12->13 14
Ld3 2 13 14->17 18
Rz4 1 15 16->13 14
Rd2 3 17 18->9 10
Rr3 2 19 20->17 18
Rz4 1 21 22->19 20
END
#save $t;
for my $n($t->inorder)
{$n->setKeysPerNode(1);
}
is_deeply $t->printKeys, <<END;
SA0 6 1
Lz4 1 2->3
Ld3 2 3->5
Rz4 1 4->3
Ld2 3 5->9
Lz4 1 6->7
Rd3 2 7->5
Rz4 1 8->7
Rd1 5 9->1
Lz5 1 10->11
Ld4 2 11->13
Rz5 1 12->11
Ld3 3 13->17
Lz5 1 14->15
Rd4 2 15->13
Rz5 1 16->15
Rd2 4 17->9
Lz4 1 18->19
Rd3 3 19->17
Lz5 1 20->21
Rd4 2 21->19
Rz5 1 22->21
END
#save $t;
$_->setKeysPerNode(2) for $t->inorder;
is_deeply $t->printKeys, <<END;
SA0 5 1 2
Lz3 1 3 4->5 6
Ld2 2 5 6->9 10
Rz3 1 7 8->5 6
Rd1 4 9 10->1 2
Lz4 1 11 12->13 14
Ld3 2 13 14->17 18
Rz4 1 15 16->13 14
Rd2 3 17 18->9 10
Lz4 1 19 20->21 22
Rl3 2 21 22->17 18
END
#save $t;
$_->setKeysPerNode(4) for $t->inorder;
is_deeply $t->printKeys, <<END;
SA0 4 1 2 3 4
Lz2 1 5 6 7 8->9 10 11 12
Rd1 3 9 10 11 12->1 2 3 4
Lz3 1 13 14 15 16->17 18 19 20
Rd2 2 17 18 19 20->9 10 11 12
Rz3 1 21 22->17 18 19 20
END
#save $t;
}
names ($tree)
Names of all nodes in a tree in order
Parameter Description
1 $tree Tree
Example:
if (1)
{my sub randomLoad($$$) # Randomly load different size nodes
{my ($N, $keys, $height) = @_; # Number of elements, number of keys per node, expected height
lll "Random load $keys";
srand(1); # Same randomization
my $t = Tree::Bulk::new->setKeysPerNode($keys);
for my $r(randomizeArray 1..$N)
{$t->insert($r, 2 * $r);
$t->check;
}
is_deeply $t->actualHeight, $height; # Check height
confess unless $t->actualHeight == $height;
is_deeply join(' ', 1..$N), $t->names; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my %t = map {$_=>2*$_} 1..$N;
for my $r(randomizeArray 1..$N) # Delete in random order
{$t->delete ($r);
delete $t{$r};
checkAgainstHash $t, %t;
check($t);
}
ok $t->empty;
is_deeply $t->actualHeight, 1;
}
randomLoad(222, 1, 11); # Random loads
randomLoad(222, 8, 8);
randomLoad(222, 4, 9);
}
balance ($t)
Balance a node
Parameter Description
1 $t Tree
Example:
if (1)
{lll "Balance";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $a = node(1,2) ->setKeysPerNode(1);
my $b = node(2,4) ->setKeysPerNode(1);
my $c = node(6,12)->setKeysPerNode(1);
my $d = node(5,10)->setKeysPerNode(1);
my $e = node(4,8) ->setKeysPerNode(1);
my $f = node(3,6) ->setKeysPerNode(1);
$a->right = $b; $b->up = $a;
$b->right = $c; $c->up = $b;
$c->left = $d; $d->up = $c;
$d->left = $e; $e->up = $d;
$e->left = $f; $f->up = $e;
$f->setHeights(1);
is_deeply $a->printKeys, <<END;
SA0 4 1
Lr2 2 2->4
Rz3 1 3->2
Rd1 3 4->1
Lz3 1 5->6
Rl2 2 6->4
END
#save $a;
$b->balance; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $a->printKeys, <<END;
SA0 4 1
Lr2 2 2->4
Rz3 1 3->2
Rd1 3 4->1
Lz3 1 5->6
Rl2 2 6->4
END
#save $a;
}
insert ($tree, $key, $data)
Insert a key and some data into a tree
Parameter Description
1 $tree Tree
2 $key Key
3 $data Data
Example:
if (1)
{lll "Insert";
my $N = 23;
my $t = Tree::Bulk::new->setKeysPerNode(1);
for(1..$N)
{$t->insert($_, 2 * $_); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
is_deeply $t->printKeys, <<END;
SA0 8 1
Lz4 1 2->3
Ld3 2 3->5
Rz4 1 4->3
Ld2 3 5->9
Lz4 1 6->7
Rd3 2 7->5
Rz4 1 8->7
Rd1 7 9->1
Lz4 1 10->11
Ld3 2 11->13
Rz4 1 12->11
Rd2 6 13->9
Lz5 1 14->15
Ld4 2 15->17
Rz5 1 16->15
Rd3 5 17->13
Lz5 1 18->19
Rd4 4 19->17
Lz6 1 20->21
Rd5 3 21->19
Rr6 2 22->21
Rz7 1 23->22
END
#save $t;
ok $t->height == 8;
}
find($tree, $key)
Find a key in a tree and returns its data
Parameter Description
1 $tree Tree
2 $key Key
Example:
if (1)
{my $t = Tree::Bulk::new;
$t->insert($_, $_*$_) for 1..20;
ok !find($t, 0); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok !find($t, 21); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok find($t, $_) == $_ * $_ for qw(1 5 10 11 15 20); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
first ($n)
First node in a tree
Parameter Description
1 $n Tree
Example:
if (1)
{my $N = 220;
my $t = Tree::Bulk::new;
for(reverse 1..$N)
{$t->insert($_, 2*$_);
}
is_deeply $t->actualHeight, 10;
if (1)
{my @n;
for (my $n = $t->first; $n; $n = $n->next) # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{push @n, $n->keys->@*
}
is_deeply \@n, [1..$N];
}
if (1)
{my @p;
for my $p(reverse $t->inorder)
{push @p, reverse $p->keys->@*;
}
is_deeply \@p, [reverse 1..$N];
}
my @p;
for(my $p = $t->last; $p; $p = $p->prev)
{push @p, reverse $p->keys->@*
}
is_deeply \@p, [reverse 1..$N];
my %t = map {$_=>2*$_} 1..$N;
for my $i(0..3)
{for my $j(map {4 * $_-$i} 1..$N/4)
{$t->delete ($j);
delete $t{$j};
checkAgainstHash $t, %t;
}
}
ok $t->empty;
is_deeply $t->actualHeight, 1;
}
last($n)
Last node in a tree
Parameter Description
1 $n Tree
Example:
if (1)
{my $N = 220;
my $t = Tree::Bulk::new;
for(reverse 1..$N)
{$t->insert($_, 2*$_);
}
is_deeply $t->actualHeight, 10;
if (1)
{my @n;
for (my $n = $t->first; $n; $n = $n->next)
{push @n, $n->keys->@*
}
is_deeply \@n, [1..$N];
}
if (1)
{my @p;
for my $p(reverse $t->inorder)
{push @p, reverse $p->keys->@*;
}
is_deeply \@p, [reverse 1..$N];
}
my @p;
for(my $p = $t->last; $p; $p = $p->prev) # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{push @p, reverse $p->keys->@*
}
is_deeply \@p, [reverse 1..$N];
my %t = map {$_=>2*$_} 1..$N;
for my $i(0..3)
{for my $j(map {4 * $_-$i} 1..$N/4)
{$t->delete ($j);
delete $t{$j};
checkAgainstHash $t, %t;
}
}
ok $t->empty;
is_deeply $t->actualHeight, 1;
}
next($tree)
Next node in order
Parameter Description
1 $tree Tree
Example:
if (1)
{my $N = 220;
my $t = Tree::Bulk::new;
for(reverse 1..$N)
{$t->insert($_, 2*$_);
}
is_deeply $t->actualHeight, 10;
if (1)
{my @n;
for (my $n = $t->first; $n; $n = $n->next) # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{push @n, $n->keys->@*
}
is_deeply \@n, [1..$N];
}
if (1)
{my @p;
for my $p(reverse $t->inorder)
{push @p, reverse $p->keys->@*;
}
is_deeply \@p, [reverse 1..$N];
}
my @p;
for(my $p = $t->last; $p; $p = $p->prev)
{push @p, reverse $p->keys->@*
}
is_deeply \@p, [reverse 1..$N];
my %t = map {$_=>2*$_} 1..$N;
for my $i(0..3)
{for my $j(map {4 * $_-$i} 1..$N/4)
{$t->delete ($j);
delete $t{$j};
checkAgainstHash $t, %t;
}
}
ok $t->empty;
is_deeply $t->actualHeight, 1;
}
prev($tree)
Previous node in order
Parameter Description
1 $tree Tree
Example:
if (1)
{my $N = 220;
my $t = Tree::Bulk::new;
for(reverse 1..$N)
{$t->insert($_, 2*$_);
}
is_deeply $t->actualHeight, 10;
if (1)
{my @n;
for (my $n = $t->first; $n; $n = $n->next)
{push @n, $n->keys->@*
}
is_deeply \@n, [1..$N];
}
if (1)
{my @p;
for my $p(reverse $t->inorder)
{push @p, reverse $p->keys->@*;
}
is_deeply \@p, [reverse 1..$N];
}
my @p;
for(my $p = $t->last; $p; $p = $p->prev) # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{push @p, reverse $p->keys->@*
}
is_deeply \@p, [reverse 1..$N];
my %t = map {$_=>2*$_} 1..$N;
for my $i(0..3)
{for my $j(map {4 * $_-$i} 1..$N/4)
{$t->delete ($j);
delete $t{$j};
checkAgainstHash $t, %t;
}
}
ok $t->empty;
is_deeply $t->actualHeight, 1;
}
inorder ($tree)
Return a list of all the nodes in a tree in order
Parameter Description
1 $tree Tree
Example:
if (1)
{my $N = 220;
my $t = Tree::Bulk::new;
for(reverse 1..$N)
{$t->insert($_, 2*$_);
}
is_deeply $t->actualHeight, 10;
if (1)
{my @n;
for (my $n = $t->first; $n; $n = $n->next)
{push @n, $n->keys->@*
}
is_deeply \@n, [1..$N];
}
if (1)
{my @p;
for my $p(reverse $t->inorder) # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{push @p, reverse $p->keys->@*;
}
is_deeply \@p, [reverse 1..$N];
}
my @p;
for(my $p = $t->last; $p; $p = $p->prev)
{push @p, reverse $p->keys->@*
}
is_deeply \@p, [reverse 1..$N];
my %t = map {$_=>2*$_} 1..$N;
for my $i(0..3)
{for my $j(map {4 * $_-$i} 1..$N/4)
{$t->delete ($j);
delete $t{$j};
checkAgainstHash $t, %t;
}
}
ok $t->empty;
is_deeply $t->actualHeight, 1;
}
delete ($tree, $key)
Delete a key in a tree
Parameter Description
1 $tree Tree
2 $key Key
Example:
if (1)
{lll "Delete";
my $N = 28;
my $t = Tree::Bulk::new->setKeysPerNode(1);
for(1..$N)
{$t->insert($_, 2 * $_);
}
is_deeply $t->printKeys, <<END;
SA0 8 1
Lz4 1 2->3
Ld3 2 3->5
Rz4 1 4->3
Ld2 3 5->9
Lz4 1 6->7
Rd3 2 7->5
Rz4 1 8->7
Rd1 7 9->1
Lz5 1 10->11
Ld4 2 11->13
Rz5 1 12->11
Ld3 3 13->17
Lz5 1 14->15
Rd4 2 15->13
Rz5 1 16->15
Rd2 6 17->9
Lz5 1 18->19
Ld4 2 19->21
Rz5 1 20->19
Rd3 5 21->17
Lz5 1 22->23
Rd4 4 23->21
Lz6 1 24->25
Rd5 3 25->23
Lz7 1 26->27
Rd6 2 27->25
Rz7 1 28->27
END
#save $t;
for my $k(reverse 1..$N)
{$t->delete($k); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $t->printKeys, <<END if $k == 17;
SA0 5 1
Lz4 1 2->3
Ld3 2 3->5
Rz4 1 4->3
Ld2 3 5->9
Lz4 1 6->7
Rd3 2 7->5
Rz4 1 8->7
Rd1 4 9->1
Lz4 1 10->11
Ld3 2 11->13
Rz4 1 12->11
Rd2 3 13->9
Lz4 1 14->15
Rd3 2 15->13
Rz4 1 16->15
END
#save $t if $k == 17;
is_deeply $t->printKeys, <<END if $k == 9;
SA0 4 1
Lz3 1 2->3
Ld2 2 3->5
Rz3 1 4->3
Rd1 3 5->1
Lz3 1 6->7
Rd2 2 7->5
Rz3 1 8->7
END
#save $t if $k == 9;
is_deeply $t->printKeys, <<END if $k == 6;
SA0 4 1
Lz2 1 2->3
Rd1 3 3->1
Lz3 1 4->5
Rl2 2 5->3
END
#save $t if $k == 6;
is_deeply $t->printKeys, <<END if $k == 4;
SA0 3 1
Rr1 2 2->1
Rz2 1 3->2
END
#save $t if $k == 4;
is_deeply $t->printKeys, <<END if $k == 3;
SA0 2 1
Rz1 1 2->1
END
#save $t if $k == 3;
is_deeply $t->printKeys, <<END if $k == 1;
Sz0 1
END
#save $t if $k == 1;
}
}
printKeys ($t)
Print the keys in a tree
Parameter Description
1 $t Tree
Example:
if (1)
{lll "Insert";
my $N = 23;
my $t = Tree::Bulk::new->setKeysPerNode(1);
for(1..$N)
{$t->insert($_, 2 * $_);
}
is_deeply $t->printKeys, <<END; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
SA0 8 1
Lz4 1 2->3
Ld3 2 3->5
Rz4 1 4->3
Ld2 3 5->9
Lz4 1 6->7
Rd3 2 7->5
Rz4 1 8->7
Rd1 7 9->1
Lz4 1 10->11
Ld3 2 11->13
Rz4 1 12->11
Rd2 6 13->9
Lz5 1 14->15
Ld4 2 15->17
Rz5 1 16->15
Rd3 5 17->13
Lz5 1 18->19
Rd4 4 19->17
Lz6 1 20->21
Rd5 3 21->19
Rr6 2 22->21
Rz7 1 23->22
END
#save $t;
ok $t->height == 8;
}
setKeysPerNode ($tree, $N)
Set the number of keys for the current node
Parameter Description
1 $tree Tree
2 $N Keys per node to be set
Example:
if (1)
{lll "Split and Refill";
my $N = 22;
my $t = Tree::Bulk::new;
for my $k(1..$N)
{$t->insert($k, 2 * $k);
}
is_deeply $t->name, "1 2 3 4";
is_deeply $t->printKeys, <<END;
SA0 4 1 2 3 4
Lz2 1 5 6 7 8->9 10 11 12
Rd1 3 9 10 11 12->1 2 3 4
Lz3 1 13 14 15 16->17 18 19 20
Rd2 2 17 18 19 20->9 10 11 12
Rz3 1 21 22->17 18 19 20
END
#save $t;
for my $n($t->inorder)
{$n->setKeysPerNode(2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
is_deeply $t->printKeys, <<END;
SA0 5 1 2
Lz3 1 3 4->5 6
Ld2 2 5 6->9 10
Rz3 1 7 8->5 6
Rd1 4 9 10->1 2
Lz4 1 11 12->13 14
Ld3 2 13 14->17 18
Rz4 1 15 16->13 14
Rd2 3 17 18->9 10
Rr3 2 19 20->17 18
Rz4 1 21 22->19 20
END
#save $t;
for my $n($t->inorder)
{$n->setKeysPerNode(1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
is_deeply $t->printKeys, <<END;
SA0 6 1
Lz4 1 2->3
Ld3 2 3->5
Rz4 1 4->3
Ld2 3 5->9
Lz4 1 6->7
Rd3 2 7->5
Rz4 1 8->7
Rd1 5 9->1
Lz5 1 10->11
Ld4 2 11->13
Rz5 1 12->11
Ld3 3 13->17
Lz5 1 14->15
Rd4 2 15->13
Rz5 1 16->15
Rd2 4 17->9
Lz4 1 18->19
Rd3 3 19->17
Lz5 1 20->21
Rd4 2 21->19
Rz5 1 22->21
END
#save $t;
$_->setKeysPerNode(2) for $t->inorder; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $t->printKeys, <<END;
SA0 5 1 2
Lz3 1 3 4->5 6
Ld2 2 5 6->9 10
Rz3 1 7 8->5 6
Rd1 4 9 10->1 2
Lz4 1 11 12->13 14
Ld3 2 13 14->17 18
Rz4 1 15 16->13 14
Rd2 3 17 18->9 10
Lz4 1 19 20->21 22
Rl3 2 21 22->17 18
END
#save $t;
$_->setKeysPerNode(4) for $t->inorder; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $t->printKeys, <<END;
SA0 4 1 2 3 4
Lz2 1 5 6 7 8->9 10 11 12
Rd1 3 9 10 11 12->1 2 3 4
Lz3 1 13 14 15 16->17 18 19 20
Rd2 2 17 18 19 20->9 10 11 12
Rz3 1 21 22->17 18 19 20
END
#save $t;
}
printKeysAndData($t)
Print the mapping from keys to data in a tree
Parameter Description
1 $t Tree
Example:
if (1)
{my $N = 22;
my $t = Tree::Bulk::new;
ok $t->empty;
ok $t->leaf;
for(1..$N)
{$t->insert($_, 2 * $_);
}
ok $t->right->duplex;
is_deeply actualHeight($t), 4;
is_deeply $t->printKeys, <<END;
SA0 4 1 2 3 4
Lz2 1 5 6 7 8->9 10 11 12
Rd1 3 9 10 11 12->1 2 3 4
Lz3 1 13 14 15 16->17 18 19 20
Rd2 2 17 18 19 20->9 10 11 12
Rz3 1 21 22->17 18 19 20
END
#save $t;
is_deeply $t->printKeysAndData, <<END; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
1 2
2 4
3 6
4 8
5 10
6 12
7 14
8 16
9 18
10 20
11 22
12 24
13 26
14 28
15 30
16 32
17 34
18 36
19 38
20 40
21 42
22 44
END
my %t = map {$_=>2*$_} 1..$N;
for(map {2 * $_} 1..$N/2)
{$t->delete($_);
delete $t{$_};
checkAgainstHash $t, %t;
}
is_deeply $t->printKeys, <<END;
SA0 3 1 3 5 7
Rr1 2 9 11 13 15->1 3 5 7
Rz2 1 17 19 21->9 11 13 15
END
#save($t);
is_deeply $t->printKeysAndData, <<END; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
1 2
3 6
5 10
7 14
9 18
11 22
13 26
15 30
17 34
19 38
21 42
END
for(map {2 * $_-1} 1..$N/2)
{$t->delete($_);
delete $t{$_};
checkAgainstHash $t, %t;
}
is_deeply $t->printKeys, <<END;
Sz0 1
END
#save($t);
}
Hash Definitions
Tree::Bulk Definition
Bulk tree node
Output fields
data
Data corresponding to each key
height
Height of node
keys
Array of data items for this node
keysPerNode
Maximum number of keys per node
left
Left node
right
Right node
up
Parent node
Attributes
The following is a list of all the attributes in this package. A method coded with the same name in your package will over ride the method of the same name in this package and thus provide your value for the attribute in place of the default value supplied for this attribute by this package.
Replaceable Attribute List
new
new
Create a new tree
Private Methods
node($key, $data, $up, $side)
Create a new bulk tree node
Parameter Description
1 $key Key
2 $data $data
3 $up Parent node
4 $side Side of parent node
setHeights ($tree)
Set heights along path to root
Parameter Description
1 $tree Tree
Example:
if (1)
{lll "Balance";
my $t = Tree::Bulk::new->setKeysPerNode(1);
my $a = node(1,2) ->setKeysPerNode(1);
my $b = node(2,4) ->setKeysPerNode(1);
my $c = node(6,12)->setKeysPerNode(1);
my $d = node(5,10)->setKeysPerNode(1);
my $e = node(4,8) ->setKeysPerNode(1);
my $f = node(3,6) ->setKeysPerNode(1);
$a->right = $b; $b->up = $a;
$b->right = $c; $c->up = $b;
$c->left = $d; $d->up = $c;
$d->left = $e; $e->up = $d;
$e->left = $f; $f->up = $e;
$f->setHeights(1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $a->printKeys, <<END;
SA0 4 1
Lr2 2 2->4
Rz3 1 3->2
Rd1 3 4->1
Lz3 1 5->6
Rl2 2 6->4
END
#save $a;
$b->balance;
is_deeply $a->printKeys, <<END;
SA0 4 1
Lr2 2 2->4
Rz3 1 3->2
Rd1 3 4->1
Lz3 1 5->6
Rl2 2 6->4
END
#save $a;
}
actualHeight($tree)
Get the height of a node
Parameter Description
1 $tree Tree
Example:
if (1)
{my $N = 22;
my $t = Tree::Bulk::new;
ok $t->empty;
ok $t->leaf;
for(1..$N)
{$t->insert($_, 2 * $_);
}
ok $t->right->duplex;
is_deeply actualHeight($t), 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $t->printKeys, <<END;
SA0 4 1 2 3 4
Lz2 1 5 6 7 8->9 10 11 12
Rd1 3 9 10 11 12->1 2 3 4
Lz3 1 13 14 15 16->17 18 19 20
Rd2 2 17 18 19 20->9 10 11 12
Rz3 1 21 22->17 18 19 20
END
#save $t;
is_deeply $t->printKeysAndData, <<END;
1 2
2 4
3 6
4 8
5 10
6 12
7 14
8 16
9 18
10 20
11 22
12 24
13 26
14 28
15 30
16 32
17 34
18 36
19 38
20 40
21 42
22 44
END
my %t = map {$_=>2*$_} 1..$N;
for(map {2 * $_} 1..$N/2)
{$t->delete($_);
delete $t{$_};
checkAgainstHash $t, %t;
}
is_deeply $t->printKeys, <<END;
SA0 3 1 3 5 7
Rr1 2 9 11 13 15->1 3 5 7
Rz2 1 17 19 21->9 11 13 15
END
#save($t);
is_deeply $t->printKeysAndData, <<END;
1 2
3 6
5 10
7 14
9 18
11 22
13 26
15 30
17 34
19 38
21 42
END
for(map {2 * $_-1} 1..$N/2)
{$t->delete($_);
delete $t{$_};
checkAgainstHash $t, %t;
}
is_deeply $t->printKeys, <<END;
Sz0 1
END
#save($t);
}
setHeight ($tree)
Set height of a tree from its left and right trees
Parameter Description
1 $tree Tree
rotateLeft ($n)
Rotate a node left
Parameter Description
1 $n Node
Example:
if (1)
{lll "Rotate";
my $a = node(1,2)->setKeysPerNode(1);
my $b = node(2,4)->setKeysPerNode(1);
my $c = node(3,6)->setKeysPerNode(1);
my $d = node(4,8)->setKeysPerNode(1);
$a->right = $b; $b->up = $a;
$b->right = $c; $c->up = $b;
$c->right = $d; $d->up = $c;
$d->setHeights(1);
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$b->rotateLeft; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$c->rotateLeft; $c->setHeights(2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$d->rotateRight; $d->setHeights(1);
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$c->rotateRight; $c->setHeights(2);
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
}
rotateRight ($n)
Rotate a node right
Parameter Description
1 $n Node
Example:
if (1)
{lll "Rotate";
my $a = node(1,2)->setKeysPerNode(1);
my $b = node(2,4)->setKeysPerNode(1);
my $c = node(3,6)->setKeysPerNode(1);
my $d = node(4,8)->setKeysPerNode(1);
$a->right = $b; $b->up = $a;
$b->right = $c; $c->up = $b;
$c->right = $d; $d->up = $c;
$d->setHeights(1);
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$b->rotateLeft;
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$c->rotateLeft; $c->setHeights(2);
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$d->rotateRight; $d->setHeights(1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
$c->rotateRight; $c->setHeights(2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $a->printKeys, <<END;
SA0 3 1
Lz2 1 2->3
Rd1 2 3->1
Rz2 1 4->3
END
#save $a;
}
insertUnchecked ($tree, $key, $data)
Insert a key and some data into a tree
Parameter Description
1 $tree Tree
2 $key Key
3 $data Data
unchain ($t)
Remove a tree from the middle of a chain. A leaf is considered to be in the middle of a chain and so can be removed with this method
Parameter Description
1 $t Tree
refillFromRight ($target)
Push a key to the target node from the next node
Parameter Description
1 $target Target tree
refillFromLeft ($target)
Push a key to the target node from the previous node
Parameter Description
1 $target Target tree
refill ($tree)
Refill a node so it has the expected number of keys
Parameter Description
1 $tree Tree
printKeys2 ($t, $in, $g)
print the keys for a tree
Parameter Description
1 $t Tree
2 $in Indentation
3 $g List of keys
checkLRU($tree)
Confirm pointers in tree
Parameter Description
1 $tree Tree
check ($tree)
Confirm that each node in a tree is ordered correctly
Parameter Description
1 $tree Tree
checkAgainstHash($t, %t)
Check a tree against a hash
Parameter Description
1 $t Tree
2 %t Expected
Index
1 actualHeight - Get the height of a node
2 balance - Balance a node
3 check - Confirm that each node in a tree is ordered correctly
4 checkAgainstHash - Check a tree against a hash
5 checkLRU - Confirm pointers in tree
6 delete - Delete a key in a tree
7 duplex - Return the tree if it has left and right children
8 empty - Return the tree if it is empty
9 find - Find a key in a tree and returns its data
10 first - First node in a tree
11 inorder - Return a list of all the nodes in a tree in order
12 insert - Insert a key and some data into a tree
13 insertUnchecked - Insert a key and some data into a tree
14 isLeftChild - Return the tree if it is the left child
15 isRightChild - Return the tree if it is the right child
16 isRoot - Return the tree if it is the root
17 last - Last node in a tree
18 leaf - Return the tree if it is a leaf
19 name - Name of a tree
20 names - Names of all nodes in a tree in order
21 next - Next node in order
22 node - Create a new bulk tree node
23 prev - Previous node in order
24 printKeys - Print the keys in a tree
25 printKeys2 - print the keys for a tree
26 printKeysAndData - Print the mapping from keys to data in a tree
27 refill - Refill a node so it has the expected number of keys
28 refillFromLeft - Push a key to the target node from the previous node
29 refillFromRight - Push a key to the target node from the next node
30 root - Return the root node of a tree
31 rotateLeft - Rotate a node left
32 rotateRight - Rotate a node right
33 setHeight - Set height of a tree from its left and right trees
34 setHeights - Set heights along path to root
35 setKeysPerNode - Set the number of keys for the current node
36 simplex - Return the tree if it has either a left child or a right child but not both.
37 simplexWithLeaf - Return the tree if it has either a left child or a right child but not both and the child it has a leaf.
38 singleton - Return the tree if it contains only the root node and nothing else
39 unchain - Remove a tree from the middle of a chain.
Installation
This module is written in 100% Pure Perl and, thus, it is easy to read, comprehend, use, modify and install via cpan:
sudo cpan install Tree::Bulk
Author
Copyright
Copyright (c) 2016-2023 Philip R Brenan.
This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.