 Hello and welcome to this session in which we will look at one of the most common applications of binary trees which are called binary search trees. So, binary search tree is used to represent sets of elements of an arbitrary type T. So, a set of type T is nothing but a collection of values of type T. Note that type T itself can be any type meaning it is just a collection of values and we want to represent a subset of those values. So, we call that type as a set of type T and the typical operations on a set are insert or delete a given value from the set or find whether a given value belongs to the set. So, we have collection of values of type T in which we want to insert or delete values and test whether a given value belongs to the set. This is one of the most commonly occurring data types and binary search trees give a very nice and efficient way of implementing or representing such sets. This also allows more complex operations like union and intersection of sets, but we will not look at those here. So, what is a binary search tree? So, we have to use represent a set of type T. So, we assume that there is a less than relation defined on the values of type T. So, given any two values of type T, we can say which value is smaller than the other. So, we have seen a less than relation can be defined on numbers and that definition can be extended to sequences of numbers and so on. So, the values in the set are stored in the nodes of a binary tree with one value per node. So, we want to represent a set of values of type T, we will make a binary tree and we will store the values in the set in the nodes of the binary tree. So, we will use value n to denote the value that is stored in node n and the basic property that is satisfied by a binary search tree is. If you take any node, so remember this is a binary tree. So, every node has a left sub tree and a right sub tree which themselves contain other nodes. So, the basic property is that for every node, the nodes in its left sub tree contain values that are less than the value of the node and the value in the node is less than the values in the right sub tree of n, right, of the node n. So, note that we only use the less than relation here, we do not need a greater than relation separately. So, any binary tree of size k can represent a set of size k, each node in the tree stores one value of the set and the standard operations on set are implemented by corresponding operations on the binary search tree representing the set. So, find x s is the operation that we want on a set which finds whether value x belongs to the set s. Equivalently, we can define an operation find x t which finds whether value x is in the set represented by the binary search tree. So, sets are represented by binary search tree and operations on the set are defined as operations on the binary search tree. So, how would find be defined? So, find of x, 5 will be always false, 5 will represent a empty set, it does not contain any values. So, find of x, 5 will be false. Now, what will be find of x plant n l r? So, if our binary search tree has root node n and it contains a left sub tree l and a right sub tree l, now we look at the value stored in the node n. If x is less than the value of node n, then we know that if x is present in the set, it must be in some node in the left sub tree of n because all the values in the left sub tree are less than the value in n and all the values in the right sub tree are greater than the value in n. So, if at all x is present in the tree, it must be in the left sub tree. So, we find x, l try to find x in the left sub tree if x is less than value of n. If value of n is less than x, then we try to find in the right sub tree and otherwise we say it is true that it x is neither less than the value of n nor value of n is less than x, which means x is equal to the value of n and therefore, we return to. Similarly, inserting a new value in a set x represented by a binary tree. So, if insert x, 5 then we create a new tree with a new node n which has both left and right sub tree empty and we store the value of x in the node n. So, the tree will be plant n 5 5 both left and right sub trees are empty, the node will contain the value x. On the other hand, if you are inserting x in an already existing tree obtained by planting l and r at node n, again we use the property of a binary search tree. If x is less than the value of n, then we know it has to be inserted in the left sub tree. So, the new tree that we get is obtained by planting at n, the left sub tree will be modified by inserting x in that. So, the left sub tree will now become insert x comma l, the right sub tree will remain as it is r. This is if x is less than the value of n. If value of n is less than x, then we insert it in the right sub tree. So, we will plant n, l will remain as it is, the right sub tree will be obtained by inserting x in r. This is if value of n is less than x. Otherwise, we do not change the tree at all. Essentially, it means x already exists in the set. So, inserting an already existing element does nothing. So, we get back the same tree with the same left and right sub tree. The delete operation is a bit more complicated. So, if we are deleting x from an empty set, we get the empty set itself. So, note that here the delete operation will delete the element if it exists. If it does not exist, it will not do anything. So, let us say how delete would work. If you are deleting a value from a binary search tree which already has a node n and a left sub tree l and a right sub tree r. Again, if x is less than the value of n, then we have to delete x from the left sub tree of n and not change the right sub tree. So, the root node will remain n. We just delete x from the value of the left sub tree or the set represented by the left sub tree and keep the right sub tree as it is. Similarly, value n is less than x, then we delete it from the right. The difficult part is when it is equal to the value stored in the root node itself. So, now we have a different operation called delete root. So, we have a binary search tree which is obtained by planting n l r and n stores some value x and we want to delete that value from the set representing it. So, delete root is a different operation that we need to define. This is undefined for the empty tree because there is no root node for the empty tree. So, delete root is not defined. Now, if the delete root operation has a tree which has a root node but its left sub tree is empty and the right sub tree is r, then it just gives us the right sub tree. So, we get rid of the value stored in the root node and the resulting tree is just the right sub tree. Similarly, if the right sub tree is empty, then deleting the root node will only give the left sub tree. And only in the case when both left and right sub trees are non-empty, we need to do something more to get rid of this value. So, now we will do a different thing. We will delete the maximum value from the left sub tree and we will place this maximum value from the left sub tree in the root node of the tree. So, the node itself will not be deleted. Node n will not be deleted. Only the value stored in the node n will be changed. Instead of storing the previous value x which we wanted to delete, we will now store the value max of l which is the largest value in the left sub tree. But this will still be less than all the values in the right sub tree. So, we still get a valid binary search tree by doing this. And now we will delete the value from the left sub tree, the max value from the left sub tree. So, the new tree is obtained by planting at the node n itself. The left sub tree will now be obtained by deleting the largest value in that. The right sub tree will remain the same. And we change the value of n to be the max value in the left sub tree. And delete max is similarly defined. So, if the max for an empty tree it is undefined. Delete max if the right sub tree is empty, then the max value is in the root node itself in which case we get just the left sub tree. On the other hand if the right sub tree is not empty, then the deleting the max will be the deleting the max from the right sub tree. So, we will get the tree with the same root node, same left sub tree, but the max value deleted from the right sub tree if the right sub tree is not empty. And similarly the max value is defined to be if it is empty it is undefined. If the right sub tree is empty the max value is in the root node itself. So, it is value of n and if the right sub tree is not empty the max value in the right sub tree. So, why our binary search is useful compared to sequences you can see that the time required for any operation depends on the height of the tree rather than its size. For every operation we call insert-delete recursively on only one of its sub trees and that sub tree always has smaller height than the original tree. So, every time we call insert on a smaller tree the height reduces by 1. So, the maximum number of times you will need to call insert-delete operation is at most the height of the tree. And for most binary trees the height is much smaller compared to their size. Whereas if you had used the sequence for representing sets the number of recursive calls would have been proportional to the length of the sequence which is the number of elements in the set. So, binary search trees give a more efficient implementation for these operations and also more convenient way of representing them. And this is also useful for sorting the values in a set. So, an in-order traversal of a binary search tree will order the nodes in increasing order of their values. And this is a very useful operation if you want to compare two sets for equality. So, if you want to do check whether two sets represented by binary search trees are equal simply do an in-order traversal look at the sequence of nodes obtained and the values in them the two sequences must be the same then the two sets are equal. And we can similarly compare whether one set is less than another and so on. So, here are some more operations that can be performed which you can try as exercises. So, we can use the binary search tree to find the kth smallest element in a set. For example, we showed how to find the maximum in general you can find the kth smallest element in a set also in the same time proportional to the height of the tree. You need to store some extra values in the nodes of the binary search tree. So, you need some modifications in the tree structure. So, not really in the tree structure, but in the values stored in the nodes to implement this. Similarly, we can write a function count x y t which counts the number of elements in the tree with value between x and y. And we can modify the find operation which instead of finding just the element x finds the element whose value is smallest but greater than or equal to x. So, if x exists it should return x itself if x does not exist it should find the smallest value which is greater than x which exists in the set. And if there is no such element it is undefined. So, we will look at some more examples of tree structures in the next session. Thank you.