# ETOOBUSY ðŸš€ minimal blogging for the impatient

# PWC130 - Binary Search Tree

**TL;DR**

On with TASK #2 from The Weekly Challenge #130. Enjoy!

# The challenge

You are given a tree.

Write a script to find out if the given tree is

`Binary Search Tree (BST)`

.According to wikipedia, the definition of BST:

A binary search tree is a rooted binary tree, whose internal nodes each store a key (and optionally, an associated value), and each has two distinguished sub-trees, commonly denoted left and right. The tree additionally satisfies the binary search property: the key in each node is greater than or equal to any key stored in the left sub-tree, and less than or equal to any key stored in the right sub-tree. The leaves (final nodes) of the tree contain no key and have no structure to distinguish them from one another.

Example 1`Input: 8 / \ 5 9 / \ 4 6 Output: 1 as the given tree is a BST.`

Example 2`Input: 5 / \ 4 7 / \ 3 6 Output: 0 as the given tree is a not BST.`

# The questions

My question about the definition is whether the leaves are considered
only the *empty* left/right nodes of a node that has a key. Another
question would be whether a node with a key always has two non-empty
left and right children.

All in all, anyway, it doesnâ€™t really matter for the implementation I have in mindâ€¦ so itâ€™s more curiosity than anything else.

# The solution

The most straightforward approach is, for me, to go recursive. In this case, in each node we will have to consider the following quantities:

- the
*key*of the node itself; - the
*minimum key*and the*maximum key*of the left child, which we will call`$lmin`

and`$lmax`

; - the same quantities for the right child, respectively
`$rmin`

and`$rmax`

.

At that node, we have the following:

- if either the left or the right child donâ€™t comply with the BST rules, then the whole tree does not either. Hence, we have to make sure that they do.
- At the specific node, we must check that the key is greater than
`$lmax`

(i.e. the maximum value on the left side) and that it is also less than`$rmin`

(i.e. the minimum value on the right side).

If both apply, then this particular node is good, and we can go back to
the parent node, reporting a success and also `$lmin`

and `$rmax`

as the
overall minimum and maximum values.

In case the tree is not perfectly assembled (e.g. a node only has a left or a right side) we will have to cope with the fact and act accordingly.

Perl goes first this time:

```
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
sub check_bst ($root) {
state $checker = sub ($node) {
return 1 unless $node;
my $key = $node->{key};
my ($lsub, $lmin, $lmax) = __SUB__->($node->{left});
return 0 unless $lsub;
($lmin, $lmax) = ($key, $key - 1) unless defined $lmin;
my ($rsub, $rmin, $rmax) = __SUB__->($node->{right});
return 0 unless $rsub;
($rmin, $rmax) = ($key + 1, $key) unless defined $rmin;
return 0 if $key < $lmax || $key > $rmin;
return (1, $lmin, $rmax);
};
return ($checker->($root))[0];
}
sub n ($k, $l = undef, $r = undef) {{key => $k, left => $l, right => $r}}
say check_bst(n(8, n(5, n(4), n(6)), n(9)));
say check_bst(n(5, n(4, n(3), n(6)), n(7)));
```

I guess that these two lines deserve some additional explanation:

```
($lmin, $lmax) = ($key, $key - 1) unless defined $lmin;
...
($rmin, $rmax) = ($key + 1, $key) unless defined $rmin;
```

In case a leg is empty, we get nothing from it (i.e. `undef`

). This
inherently means that the sub-tree on that side is compliant, hence:

- to make the test succeed, we set
`$lmax`

to be smaller than the key (`$key - 1`

), and`$rmin`

to be greater than it (`$key + 1`

). - on the other hand, the missing extreme is set to be equal to
`$key`

, because this is the value we want to send back to the parentâ€™s call.

Time for Raku now, which is a simple translation:

```
#!/usr/bin/env raku
use v6;
sub check-bst ($root) {
my sub checker ($node --> Array()) {
return 1 unless $node;
my ($key, $left, $right) = $node<key left right>;
my ($lsub, $lmin, $lmax) = checker($left);
return 0 unless $lsub;
($lmin, $lmax) = ($key, $key - 1) unless defined $lmin;
my ($rsub, $rmin, $rmax) = checker($right);
return 0 unless $rsub;
($rmin, $rmax) = ($key + 1, $key) unless defined $rmin;
return 0 if $key < $lmax || $key > $rmin;
return (1, $lmin, $rmax);
}
return checker($root)[0];
}
sub n ($k, $l = Nil, $r = Nil) {(key => $k, left => $l, right => $r).hash}
put check-bst(n(8, n(5, n(4), n(6)), n(9)));
put check-bst(n(5, n(4, n(3), n(6)), n(7)));
```

And with thisâ€¦ itâ€™s all for this post, I hope you enjoyed it and stay safe anyway!

*Comments? Octodon, Twitter, GitHub, Reddit, or drop me a line!*