 Hello and welcome to this session in which we will be looking at our first examples of what are called non-linear data structures or non-sequential data structures and trees are the simplest examples of this. So what is a sequence, in a sequence as we have seen for every element except the first and the last there is a unique next element and a previous element. In a tree we generalize this property and element can have more than one next element but every element still has exactly one previous element except for the first one. So trees are the generalization of sequences instead of having just one next element for each element we can have more than one and trees can give more compact representations for other data types and also operations on trees are more efficient compared to sequences. So let us define what are called binary trees formally, so there are many kinds of trees and binary trees are the simplest examples of trees so let us define what they are. Again just as in case of sequences they are defined by a single operation so the push operation was used to define sequences for binary trees we will define an operation called plant. So again an empty binary tree always exists so phi is always a binary tree and if we have two binary trees L and R then by planting them using the operation plant N L R we get a new binary tree. So here N denotes a node or essentially a data type that can store values of any type in that. So N a node is considered a generic type it can store values of any other type and for defining a tree we just think of node as being a type and we build a new tree from two existing trees L and R by planting them at node N. So in a sequence the push operation used an element of type T and an existing sequence of type T to add one more element to that. In a binary tree we use two already existing trees L and R and a node N which can store any kind of data and build a new binary tree and all binary trees can be obtained from the empty tree using the plant operation. So there are some terms used in binary trees that we will define so let us say we have a binary tree T obtained by planting L and R at a node N then N is called a root node of the tree T, L is called the left sub tree of T and also of the node N of the root node and R is the right sub tree of T. So L and R are themselves binary trees and they are called the sub trees of the tree T. If L or R is not empty but it itself is the form plant M L1 L2 then M is called the left or right child of N and N is the parent of N that is if L is not empty then its root is called the left child of N and if R is not empty then its root is called a right child of N and N is called a parent of that. And we said T is said to contain the node N and all the nodes that are contained in the left and right sub tree. So T can also be thought of as consisting of a set of nodes its root node and the nodes that are contained in the left and right sub tree. So note that when we build a tree using the plant operation we assume that the node N is a new node which is not contained in the two existing trees L and R. So we take a new node and two existing trees and plant them at node N make L the left sub tree and R the right sub tree. So operations on binary trees are defined in a way very similar to what we did for numbers and sequences. We define the operation for the empty tree which is a base case and assuming it is defined for trees N, L, R define it for the tree obtained by planting L and R at a node N and this will define the operation for all binary trees because every binary tree can be obtained using the plant operation. Let us look at some examples. So height of a binary tree, height of the empty tree is defined to be 0 and height of a tree obtained by planting L and R at a node N is defined to be 1 plus. So 1 plus is essentially the next operation of numbers. We take the maximum of the height of L and height of R. So they have defined the height for the tree L, we have defined the height for the tree R, we take the maximum of their height and take the next of that that is 1 plus that is the height of the tree obtained by planting L and R at N. So here max is the maximum function on numbers which we can define in our standard way. Max of 0 comma N is always N for all N and max of next N comma N is next of N if max of MN is equal to N otherwise it is equal to N. Similarly we can define the size of a tree. Size is nothing but the total number of nodes in the tree. Size of the empty tree is 0 and size of the tree obtained by planting L and R at node N is we take the size of L, add the size of R to it and add one more to it for the node N itself. So it is next of add of size L comma size R. So when do we consider two binary treats to be equal? So equality is again a function that we need to define on any type when are two values of a given type considered to be equal. So the empty tree is always equal to itself. It is not equal to any tree obtained by planting two trees L1, R1 at any node M and similarly the tree plant N, L, R is not equal to the empty tree for any L and R and if I have two trees one planted at node N, L and R with left sub tree L, right sub tree R, another planted at node M with left sub tree L1 and right sub tree R1. Then we say the two trees are equal if L is equal to L1 and R is equal to R1. So the node itself plays no role in the definition of the equality. The node is essentially just an abstract object which can store data. We do not particularly care about the value of the node itself. It is just a sort of way of denoting a variable which can hold some data. So equality of trees is only defined if for the root nodes of both the trees that left sub trees are equal and the right sub trees are equal. Then the two trees are considered to be equal. So there are some special types of binary trees which are very useful in some applications. So we again define them as a function which returns true if the tree has that property otherwise it does not return, it returns false. So full trees are defined as follows. The empty tree is always considered to be full. Full of a tree obtained by planting L and R at node M. If the heights of L and R are different then this is false. It is not a full tree or if the heights are equal then both L and R must be full in which case full of plant N, L, R will be true. So essentially a full binary tree if it has height edge it will consist of a left sub tree which is a full binary tree of height 1 less and the right sub tree will also be a full binary tree of height 1 less. So you can see that the total number of nodes in a full binary tree of height edge will be 2 raised to h minus 1 and for every node the left and the right sub tree will have the same size. So another example is a complete binary tree. Complete binary trees can exist with any number of nodes unlike full binary trees. So again complete is defined as for empty tree it is complete always complete. Complete of tree obtained by planting N, L and R when is this complete. So if height of L is equal to the height of R then we require that the left sub tree must be a full tree and the right sub tree must be a complete tree. So there is an asymmetry in the definition here if the heights are equal then the left sub tree must be full and the right sub tree must be complete. Otherwise if height of L is 1 more than the height of R then L itself must be a complete tree and R must be a full tree. These are the only cases when complete will be true and if the height of L is not equal to the height of R and it is not equal to 1 plus height of R then complete will be false. There is a different way of defining complete tree but you can see this is equivalent to many other definitions that you will find elsewhere. So tree traversals is a way of finding out all the nodes in a tree and this is a useful operation in many many applications. So it is a way of essentially constructing a sequence of all the nodes in the tree. So tree consists of all the nodes. It is root nodes and the nodes contained in its left and right sub trees and this gives a way of ordering all of these nodes and making a sequence of them. So there are three orders defined in order pre-order and post-order. So these are again easy to define inductively. Assuming you have defined them for L and R you can define it for this. So in order of empty or pre-order or post-order of empty is empty. In order for plant NLR it is essentially we concatenate the in order of L and push the sequence N in that. The sequence consisting of just the root node N concatenate these two and then concatenate in order of R for that. In pre-order we first put the node N then take the pre-order of L and then the pre-order of R and in post-order we do the other way. Take post-order of L, post-order of R and then the node N. So here are some exercises that you can try on binary tree. So let TN denote the number of different binary trees of size N. How many different trees do they exist? So you can try to write a recurrence relation for TN to compute this number. Now suppose you have given the sequence of nodes in a binary tree obtained by in order and pre-order traversal. So these two sequences actually uniquely represent the binary tree. So an alternative way of representing a binary tree is just the two sequences of nodes. One is the in order sequence another is the pre-order sequence. And we say two nodes in a binary tree are siblings if they have the same parent. So if one is the left child and other is the right child of a node then they are siblings. So write a function to count the number of pairs of siblings in a binary tree. So we will look at more examples of trees in the next session. Thank you.