馃攳
Check if a binary tree is binary search tree or not - YouTube
Channel: mycodeschool
[0]
In this lesson, we're going to solve a
simple problem on binary tree
[3]
which is also a famous programming
interview question,
[7]
and the problem is given a binary tree
[10]
we need to check if the binary tree is a
binary search tree
[14]
are not. As we know a binary tree is a
tree
[18]
in which each node can have atmost two
children.
[22]
All these trees that I have drawn here are
binary trees,
[25]
but not all of them are binary search
trees. Binary search tree,
[30]
as we know is a binary tree in which for
each node
[33]
value of all the nodes in left subtree
is lesser
[37]
and if you want to allow duplicates we
can say lesser or
[40]
equal and value of all the nodes in
right subtree
[43]
is greater. We can define binary search
tree as
[46]
a recursive structure like this. Elements in
left subtree must be lesser or equal
[52]
and elements in right subtree must be
greater and this should be true for all
[56]
nodes and not just a root node,
[58]
so left and right subtrees should
themselves also be binary search trees.
[63]
Of these binary trees that I'm showing
here,
[67]
A and C are binary search trees but B
[71]
and D are not. In B for the root node
with value 10,
[75]
we have 11 in its left subtree which
is greater than 10
[79]
and in a binary tree for any node all
values in its
[83]
left subtree must be lesser. In D we are good
for the root node.
[87]
The value in root node is 5 and we
have
[91]
1 in left subtree which is lesser and
we have 8, 9 and 12
[95]
in right subtree which are greater. So we are
good for the root node
[99]
but for this node with value 8, we have
9
[103]
in its left. So this tree is not a
binary search tree.
[106]
So how should we go about solving this
problem. Basically,
[110]
I want to write a function that should
take pointer or reference to root
[114]
node of a binary tree as argument and
function should return true
[118]
if the binary tree is BST, false otherwise.
[122]
This is how my method signature look
like in C++.
[125]
In C, we do not have boolean types so
[129]
return type here can be int. We can return
[132]
1 for true and 0 of false.
[135]
I'll also write the definition of node here.
[138]
For a binary tree node would be
structure
[142]
with 3 fields, 1 to store data and 2
[145]
to store addresses of left and right
children. In my definition of node here,
[149]
data type is integer
[151]
and we have 2 pointers to node to store
addresses of
[155]
left and right children. Okay coming back
to the problem
[159]
there are multiple approaches and we're
going to talk about
[162]
all of them. The first approach that I'm
going to talk about
[165]
is easy to think of but it's not so
efficient
[168]
but let's discuss it anyway. We are saying
that for a binary tree to be called
[174]
binary search tree,
[175]
it should have recursive structure like
this. For the root node
[180]
all the elements in left subtree must be
lesser or equal
[183]
and all the elements in right subtree
must be greater, and left and right
[187]
subtrees
[188]
should themselves also be binary search
trees. So let's just check for all of this.
[194]
I'm going to write a function named
IsSubtreeLesser
[197]
that will take address of root node
of a binary tree
[201]
or subtree and and integer value
[204]
as argument and this function will return
true if
[208]
all the elements in the subtree are lesser
so than this value
[212]
and similarly I'll write another function
named IsSubtreeGreater
[216]
that will return true if all the
elements in a subtree
[219]
are greater than the given value. I had just
[223]
declared this functions. I'll write body of
these functions later.
[226]
Let's come back to this function
IsBinarySearchTree.
[229]
In this function, I am going to say that if
all elements in left subtree are
[234]
lesser and I'll verify this by making
a call to IsSubtreeLesser function
[238]
passing it
[239]
address of left child of my current
root.
[242]
Left child would be the root of current
subtree and the data in root.
[247]
This function will return true
if all the elements in left subtree
[252]
would be lesser than the data in root.
Now the next thing that I want to check
[256]
for is
[257]
if elements in right subtree are greater
than the data in root or not.
[262]
These two conditions are not sufficient.
We also need to check if left
[266]
and right subtrees are binary search
trees are not.
[269]
So I'll add two more conditions here
have made a recursive call to
[273]
IsBinarySearchTree function passing it address
of left child
[277]
and I have made another call passing
address of right child
[280]
and if all these four function call
IsSubtreeLesser, IsSubtreeGreater
[285]
and IsBinarySearchTree for left and
right subtrees
[289]
return true if all these four checks
pass then
[293]
our tree is a binary search tree. We can
return true
[297]
else we need to return false. There is
only one thing that the a missing in
[301]
this function now.
[303]
We are missing the base case. If the route is null
that is
[306]
if the tree or subtree is empty, we can
return true.
[310]
This is the base case for our recursion
where we should stop.
[314]
With this much of code IsBinarySearchTree
function is complete
[318]
but let's also write IsSubtreeLesser and
ItsSubtreeGreater
[321]
functions because they are also part
of our logic.
[325]
This function has to be a generic function
that should check
[328]
if all the elements in a given tree are
lesser than
[332]
a given value or not. We will have
to traverse the complete
[336]
tree or subtree and see value in all
nodes and compare
[340]
these values against this given integer.
I'll first handle the base case in
[345]
this function.
[346]
If the tree is empty, we can return true
else we need to check if the data in
[350]
root
[351]
is less than or equal to the given value
and we also need to recursively check if
[356]
left and right subtrees of the current
root have
[359]
lesser value or not. So I'm adding two
more conditions here.
[363]
I'm making two recursive calls one for the
left subtree and
[367]
another for the right subtree. If all these
three conditions are true
[372]
then we are good else we can return
false. IsSubtreeGreater function will
[376]
be very similar.
[377]
Instead of writing these two functions
IsSubtreeLesser
[380]
and IsSubtreeGreater, we could
also do something like this.
[385]
We could find the maximum left subtree
[389]
and compared it with the data in root,
if maximum of a subtree is lesser
[394]
then all the elements a lesser and
similarly if the minimum of
[398]
a subtree is greater all the elements had
greater.
[401]
For the right subtree, we could find a
minimum. So instead of writing these two
[405]
functions IsSubtreeLesser
[407]
and IsSubtreeGreater, we could write
something like find max
[410]
and find min and this would also fit.
[413]
So this is a solution using one of the
approaches.
[416]
Let's quickly run this code on an example
binary tree and see how it will execute.
[421]
I have drawn a very simple binary tree
here which actually is a binary search
[425]
tree.
[427]
let's assume some addresses for these
nodes the tree.
[430]
Let's say the root node is that address
200 and
[433]
I'll assume some random addresses for
other nodes as well.
[439]
To check if this binary tree is a binary
search tree or not,
[443]
we will make a call to
IsBinarySearchTree function.
[447]
I'm writing IBST here as Shortcut for
IsBinarySearchTree
[451]
because I'm short of space here. So I'll
make a call to this function
[455]
maybe from the main function passing
addressed 200,
[459]
address of the root node. For
this function call
[462]
address in this local variable address
collected in this local variable root
[467]
will be 200. Root is not null.
[470]
Null is only a macro for address 0.
[473]
For this call root is not null, so we
will not return true at this line.
[478]
We will go to the next if. Now here, we
will make a call to
[482]
IsSubtreeLesser function. Arguments
passed will be address
[486]
of left child which is 150 and
[489]
7 the data in node at 200.
[492]
Execution of the calling function will pause
and
[496]
will resume only after the called
function returns.
[499]
Now in this call to IsSubtreeLesser,
root is not null so
[503]
we will not return true at first line.
We will go to the next
[507]
if. Now here the first condition is if
[510]
data in root this time
[513]
is 150 because on this call is for this
left subtree
[518]
and for this left subtree address of
root is 150.
[521]
Data in root is 4 which is lesser than
[526]
7, so the first condition is true and we
can go to the second condition which is
[531]
a recursive call.
[532]
This call will pause and we will go
to the next call.
[536]
Here once again the data in node
[540]
at 180, 1 is lesser than 7
[543]
so first condition is true and we will
make
[547]
recursive call. Left subtree for node at
180
[550]
is null. There is no left child so
[553]
we will return at first line. Root is null
this time.
[557]
This particular call will simply to return
true. Now in this previous call when
[560]
root is 180,
[562]
second condition for if is also true.
So
[565]
we will make another call for right
subtree. Once again address passed
[569]
will be 0 and we will simply return
true and now for this call
[573]
IsSubtreeLesser 187, all three conditions
are true.
[578]
So this guy can also return true and now
ISL 150,7 will resume.
[583]
Now this guy will make a recursive
call for the right subtree
[587]
and this guy after everything will also
return true.
[591]
Now for this call because all 3
conditions in the if statement are true,
[596]
this guy will also return true and now
IsBinarySearchTree function will
[600]
resume.
[602]
For this call we have evaluated the
first condition
[605]
we have got true now this guy will make
another call
[608]
to IsSubtreeGreater, passing address of
right child and value 7.
[614]
This guy after everything will return
true and now we will have 2 recursive
[619]
calls,
[620]
to check if left and right subtree are
binary search trees on not.
[624]
We will first have a call for the left
subtree.
[628]
The execution will go on like this but I
want you to see something.
[632]
Each call to binary search tree
function,
[635]
we are comparing the data in root with
all the elements in left subtree and
[639]
then all the elements in right subtree.
[641]
This example tree could be really large
then in that case
[646]
in the first call IsBinarySearchTree
for this complete tree,
[650]
we would recursively traverse this
whole left subtree
[654]
to see whether all the values in this
subtree
[657]
are less than 7 or not and then we
will traverse all nodes in this right subtree
[662]
to see if values have greater than 7
or not and then
[665]
in next call IsBinarySearchTree,
when we would be validating with this
[670]
particular subtree is BST or not.
[672]
We would recursively traverse this
subtree if values are lesser than 4
[677]
or not
[677]
and this subtree to see if value so greater
than 4 or not.
[681]
So all in all during this whole process
there will be a lot of traversal.
[685]
Data in nodes will be read and
compared multiple times.
[689]
If you can see all nodes in this
particular subtree
[693]
will be traversed once in call to
IsBinarySearchTree for 200.
[697]
When we will compare value in these
nodes with 7
[701]
and then these nodes will once again be
traversed
[705]
in call to IsBinarySearchTree for
150 when
[708]
they will be compared with 4. They will
be traversed in call to
[713]
IsSubtreeLesser.
[714]
All in all these two functions
IsSubtreeLesser
[717]
and IsSubtreeGreater very expensive.
For each node, we are looking at all nodes in
[722]
its subtrees.
[723]
There is an efficient solution in which
we do not need to compare
[727]
data in a node with data in all nodes
in its
[730]
subtrees and let's see what the solution
is.
[733]
What we can do is we can define a
permissible
[736]
range for each node and data in that node
must be in that range
[741]
we can start at the root node with a
range
[744]
-infinity to infinity, because for
the root node
[747]
there is no upper and lower limit and
now as we are traversing we can set a range
[753]
for other nodes.
[754]
When we are going left, we need to reset
the upper bound
[757]
so for this node at 150, data has to
be between
[761]
-infinity and seven. Data in left
child cannot be greater than data in
[766]
root.
[767]
If we're going right, we need to set the
lower bound
[770]
for this node at 300 range would be 7 to
infinity.
[775]
7 is not included in the range. Data has
to be strictly greater than 7.
[780]
For this node at 180, the range will
be -infinity to 4.
[784]
For this node with value 6 lower bond will
be 4 and upperbound would be 7.
[790]
Now my code will go like this. My
function IsBinarySearchTree will take
[795]
two more arguements,
[796]
an integer to mark lower bound or
min value
[800]
and another integer to mark the upper
bound or max value
[803]
and now instead of checking whether all
the elements in left subtree are lesser than
[807]
the data in root
[808]
and all the elements in right subtree
are greater than the date in root or not.
[813]
We will simply check whetheer data in root
is
[816]
in this range or not. So I'll get rid of
these two function call
[820]
IsSubtreeGreater
[821]
and IsSubtreeGreater which are really
expensive and I'll
[824]
add these two conditions. Data in root
must be greater than min value
[829]
and data in root must be less than max
value. These two checks will take
[833]
constant time.
[834]
IsSubtreeLesser and IsSubtreeGreater
functions were not taking
[837]
constant time.
[838]
Running time for them was proportional
to number of nodes in the subtree.
[842]
Okay now these two recursive calls
should also have two more arguements.
[847]
For the left child lower bound will not
change,
[850]
upper bound will be to data in current
node and for the right child, upper
[855]
bound will not change
[856]
and lower bond will be data in current
node. This recursion looks good to me. We
[861]
already have to base case written.
[863]
The only thing is that the Caller of this
IsBinarySearchTree function
[868]
may only want to pass the address of root
node so what we can do is instead of
[872]
naming this function IsBinarySearchTree.
We can name this function
[876]
as a utility function like
IsBstUtil
[880]
and we can have another function name
IsBinarySearchTree
[884]
in which we can take only to address of
root node and this function can call
[889]
IsBstUtil to function passing address
of root.
[893]
Minimum possible value in integer
variable for -infinity
[896]
and maximum possible value in integer
valuable for
[900]
+infinity INT_MIN and INT_MAX
here are macros
[904]
for a minimum and maximum possible
values in Int.
[907]
So this is a solution using second
approach which is quite efficient.
[912]
In this recursion will go to each node
once and at each node we will take
[916]
constant time
[917]
to see whether the data at node is in a
defined range or not
[921]
and time complexity would be O(N)
where N is number of nodes in the
[925]
binary tree.
[926]
For the previous algorithm, time
complexity was O(N^2).
[930]
One more thing, in this code I have not
handled
[933]
the case that Binary search tree can
have duplicates.
[937]
I am saying that elements in left subtree
must be strictly lesser and elements in
[942]
right subtree
[943]
must be strictly greater. I leave it for
you to see how you will
[946]
allow duplicates. There is another
solution to this problem.
[950]
You can perform in order traversal of
binary tree
[954]
and if the tree is binary search tree
you would read the data in
[957]
sorted order. In-order traversal of a
[961]
binary search tree gives a sorted list. You can
do some hack
[965]
while performing in order traversal and
check if you're getting the elements in
[968]
sorted order or not.
[970]
During the whole traversal you only need
to keep track of
[973]
previously read node and at any time
data in a node that you're reading
[977]
must be greater than the data in previously read
node.
[980]
Try implementing this solution, it will be
interesting. Okay I'll stop here now.
[984]
In cominng lessons, We will discuss some
more problems on Binary tree.
[988]
Thanks for watching.
Most Recent Videos:
You can go back to the homepage right here: Homepage





