# Introduction

Lists, stacks, and queues, are all linear structures: in all three data structures, one item follows another. Trees will be our first non-linear structure:
 

More than one item can follow another. The number of items that follow can vary from one item to another.

Trees have many uses:
   

representing family genealogies as the underlying structure in decision-making algorithms to represent priority queues (a special kind of tree called a heap) to provide fast access to information in a database (a special kind of tree called a b-tree)

Here is the conceptual picture of a tree (of letters):

   

each letter represents one node the arrows from one node to another are called edges the topmost node (with no incoming edges) is the root (node A) the bottom nodes (with no outgoing edges) are the leaves (nodes D, I, G & J)

So a (computer science) tree is kind of like an upside-down real tree...

A path in a tree is a sequence of (zero or more) connected nodes; for example, here are 3 of the paths in the tree shown above:

The length of a path is the number of nodes in the path, e.g.:

The height of a tree is the length of the longest path from the root to a leaf; for the above example, the height is 4 (because the longest path from the root to a leaf is A → C → E → G, or A → C → E → J). An empty tree has height = 0. The depth of a node is the length of the path from the root to that node; for the above example:
  

the depth of J is 4 the depth of D is 3 the depth of A is 1

 The level of a node is the length of the path from the root to that node  The depth of a tree is the maximum level of any node of any node in the tree  The degree of a node is the number of partitions in the subtree which has that node as the root  Nodes with degree=0 are called leaves Given two connected nodes like this:

Node A is called the parent, and node B is called the child. A subtree of a given node includes one of its children and all of that child's descendants. The descendants of a node n are all nodes reachable from n (n's children, its children's children, etc.). In the original example, node A has three subtrees:
1. B, D 2. I 3. C, E, F, G, J.

An important special kind of tree is the binary tree. In a binary tree:

we can use a List to keep all of the child pointers: class Treenode { // *** fields *** private Object data. B's left child is E and its right child is D. a node can be represented using a class with 3 fields: one for the data in the node. in the second tree. private BinaryTreenode rightChild.) As we know. private List children.  Each node has 0. Representing Trees Since a binary-tree node never has more than two children. since a general-tree node can have an arbitrary number of children. plus two child pointers: class BinaryTreenode { // *** fields *** private Object data. a fixed number of child-pointer fields won't work. Each child is either a left child or a right child. Here are two examples of binary trees that are different: The two trees are different because the children of node B are different: in the first tree. 1. } However. consider this general tree (a simplified version of the original example): . For example. Also note that lines are used instead of arrows. or 2 children. B's left child is D and its right child is E. We sometimes do this because it is clear that the edge goes from the higher node to the lower node. Instead. } (Note that the items in the List will be of type Treenode. a list can be represented using either an array or a linked-list. private BinaryTreenode leftChild.

we started with the first node and visited each node in turn. the best possible complexity is O(N) for a tree with N nodes. All of our traversal methods will achieve this complexity.For the array representation of the List (where the array has an initial size of 4) we would have: TEST YOURSELF #1 Draw a similar picture of the tree when the List fields are implemented using linked lists. . solution Tree Traversals It is often useful to iterate through the nodes in a tree:    to print all values to determine if there is a node with some property to make a copy When we iterated through a List. Since each node is visited.

and we print the letter in each node when we visit that node. all described below. for all the subtrees of the root visit the root If we use a postorder traversal on the example tree given above. perform a postorder traversal of the first subtree of the root perform a postorder traversal of the second subtree of the root etc. level order. 3. 4. and one more for binary trees: preorder. the goal is to visit the nodes in the following order: .For trees. There are three common traversal orders for general trees. 4. Postorder A postorder traversal is similar to a preorder traversal. We will use the following tree to illustrate each traversal: Preorder A preorder traversal can be defined (recursively) as follows: 1. then visit all nodes "1 level away" (depth 2) from the root (left to right). 2. for all the subtrees of the root If we use a preorder traversal on the example tree given above. postorder. there are many different orders in which we might visit the nodes. then all nodes "2 levels away" (depth 3) from the root. etc. and in-order. the following will be printed: A B D C E G F H I. except that the root of each subtree is visited last rather than first: 1. the following will be printed: D B G E H I F C A. Level order The idea of a level-order traversal is to visit the root. and we print the letter in each node when we visit that node. visit the root perform a preorder traversal of the first subtree of the root perform a preorder traversal of the second subtree of the root etc. 3. For the example tree. 2.

The (recursive) definition is: 1. perform an in-order traversal of the left subtree of the root 2.out. perform an in-order traversal of the right subtree of the root If we print the letters in the nodes of our example tree using an in-order traversal.enqueue(it. } } TEST YOURSELF #2 Draw pictures of Q as it would be each time around the outer while loop in the code given above for the example tree given above. Iterator it = L. i.getData()).iterator().next()). which implicitly uses a stack). TEST YOURSELF #3 . Here's how to print the data in a tree in level order. visit the root 3. and using an iterator to access the children of each node (we assume that the root node is called root. before.. after or in-between.print(n.empty()) { Treenode n = Q.hasNext()) { Q.getChildren(). postorder and in-order traversals is where the node is visited in relation to the recursive calls. List L = n. while (it.e. System. Therefore. an in-order traversal only makes sense for binary trees. solution In-order An in-order traversal involves visiting the root "in between" visiting its left and right subtrees.dequeue(). the following will be printed: D B A E G C H F I The primary difference between the preorder.enqueue(root) while (!Q. using a queue Q.A level-order traversal requires using a queue (rather than a recursive algorithm. and that the Treenode class provides a getChildren method): Q.

What is printed when the following tree is visited using (a) a preorder traversal. (b) a postorder traversal. and (d) an in-order traversal? Answers to Self-Study Questions for Trees Test Yourself #1 Test Yourself #2 . (c) a level-order traversal.

The output would be: A B C D E F G H I Test Yourself #3 (a) A B D H E I C F J K G (b) H D I E B J K F G C A (c) A B C D E F G H I J K (d) D H B I E A J F K C G Tree Traversal Algorithms: 1: DEPTH-FIRST: Inorder: 1. Traverse right subtree Preorder: 1. Visit node (i. Traverse left subtree 2. Visit node 2.e. Traverse Left . process node) 3.

Traverse right Post-order: 1.3. operators in non-leaf nodes: inorder traversal: (LNR) (A-B)+((C/D)*(E-F)) A-B+C/D*E-F (paranthesis assumed) postorder traversal: (LRN) AB-C/EF-*+ preorder traversal: (NLR) +-AB*/CD-EF . Traverse right 3. Traverse left 2. Visit node Example: An arithmetic expression tree stores operands in leafs.

b.d. While queue is not empty 2.e. Remove front node from queue and visit it 2.1. eg. Traversal sequence a. calculate.Note: Postorder traversal. postorder and inorder traversals are "depth-first" A breath-first traversal algorithm. Insert right child . push result back Conditional expression syntax: CONDITION? True-case-EXP:False-case-EXP The preorder. with the following implementation of visit : if operand PUSH if operator POP two operands.3. Insert Left child 2.c.2.f Algorithm Level-Traverse 1. Insert root node in queue 2.

indicating thenumber of nonempty key values in that node. (It may be empty).< key(m-1) in other words. we have an additional entry at the leftmost field of every node. A non empty m_way search tree has the following properties: a) It has nodes of type: b) key1 < key2 <..M_WAY SEARCH TREE Definition: An m_way search tree is a tree in which all nodes are of degree<=m. 1<=i<m-1 c) All Key values in subtree Ti are greater than Keyi and less than Keyi+1 Sometimes. Example: 3_way search tree: Nodes will be of type: .. keyi<key(i+1).

b) The tree is balanced. (If we modify all link fields of leaf nodes to point to special nodes called failure nodes are at the same level) Example: B_tree of order 3: .B_TREES A B_tree of order m is an m_way search tree (possibly empty) satisfying the following properties (if it is not empty) a) All nodes other than the root node and leaf nodes have at least m/2 children.

Now. add a new failure node. we do a search for 38 in the given b_tree. it's parent node does not have any space for a key value. into a B-tree .Inserting new key values to B_tree: . which is marked as "+" in the following figure. Insert 38 there . assume we create a new node instead of . However. We'll always insert at the leaf nodes.) . we hit the failure node marked with "*" . (It must be balanced. We do the search and hit the failure node "~". We want to insert a new key value: x. insert 55 to this B_tree. The parent of that failure node has only one key value so it has space for another one. The resulting tree must also be a B-tree. 2) Now. and return. Example: 1) Insert 38 to the B_tree of the above example: First of all.

So we end up. let us insert 37 to this B_tree: We search for 37. and hit a failure node between 35 and 38. 3) Now. So.we have to create: .

If we can not insert to the root node. and 33. the height of the B_tree increases by 1 in such a case. For example try to insert 34. we end up with. .So. 32. Thu. we split and create a new root node.

and Delete Operations is O(log n). 4. Note that inorder traversal of a binary search tree always gives a sorted sequence of the values. where n is the number of nodes in the tree. we obtain a completely skewed BST. then our search procedure ends in a null link. Notice that this tree is obtained by inserting the values 13. This provides a way of sorting a given sequence of keys: first. the worst case complexity of searching or inserting an element into a BST having n nodes is O(n). This is a direct consequence of the BST property. Figure 4. 5. Note that the highest valued element in a BST can be found by traversing from the root in the right direction all along until a node with no right link is found (we can call that the rightmost element in the BST).1 if the tree has n nodes.Deletion algorithm is much more complicated! It will not be considered here. create a BST with these keys and then do an inorder traversal of the BST so created. 11. If x is present. this search procedure will lead us to the key. If the key we are seeking is present. If x is not present. The height of such a tree is n . 6. 2. starting from an empty tree. If we repeatedly insert a sorted sequence of values to form a BST. 12. Binary Search Tree           A prominent data structure used in many systems programming applications for representing and managing dynamic sets. 10. It is at this position of this null link that x will be included. we first search for x. DEF: A binary tree in which the nodes are labeled with elements of an ordered dynamic set and the following BST property is satisfied: all elements stored in the left subtree of any node x are less than the element stored at x and all elements stored in the right subtree of x are greater than the element at x. 9. 18 in that order. 1. The lowest valued element in a BST can be found by traversing from the root in the left direction all along until a node with no left link is found (we can call that the leftmost element in the BST). Insert. 8. Average case complexity of Search. 14. Search is straightforward in a BST. Thus. If we need to insert an element x. 3. Insertion in a BST is also a straightforward operation. If the key is not present.14: An example of a binary search tree . An Example: Figure 4.14 shows a binary search tree. 7. we end up in a null link. Start with the root and keep moving left or right using the BST property. there is nothing to do.

if we use an array to implement a tree we have to set a limit on the number of nodes we will permit in the tree. we'll just look at one. Here is the biggest binary tree of depth 3: . Implementing a Tree in an Array How can we represent an arbitrary binary tree in an array? In fact. and make the array big enough to hold any binary tree of this height (or less).4. Our strategy is to fix the maximum height of the tree (H). We'll need an array of size (2**H)-1. Because an array's length is fixed at compile time. there are numerous ways to do this.

If we picked H=3 as our limit.. F is in position 2*3 (6). It also makes it easy to go from a node to its parent: the parent of node I has index (I div 2). E is in position 2*2+1 (5). This could be done any way you like. What we do now is assign each of nodes to a specific position in the array.. For example. then every tree we might build will be a subtree of this one . a tree with N nodes does not necessarily occupy the first N positions in the array.this is the key insight behind our implementation. just double the node's index (and add 1 to go right). left child of node in array position K: array position 2K right child of node in array position K: array position 2K+1 So D is in position 2*2 (4). G is in position 2*3+1 (7). the tree: Somehow we need to keep track of which array elements contain valid information. This figure shows the array position associated with each node: This particular arrangement makes it easy to move from a node to its children. Two possibilities: . but a particular easy and useful way is:       root of the tree (A): array position 1 root's left child (B): array position 2 root's right child (C): array position 3 . Using this strategy.

i<N. So: 1. can traverse the tree by going through the array from first to Nth position. these problems go away. each node stores information saying which of its children exist 2. for(i=0. each array position stores information saying if it is a valid node. if we add a new value. it must go in position N+1. if there are N nodes in a complete tree. look again at the earlier picture. only need to keep track of N in order to know which array positions contain valid information. as usual. We have insisted that heaps be complete trees precisely so that they will have this very nice implementation in arrays. Because of the way we assigned nodes to positions.i++) { process node in position i.1. 2. It is a useful exercise to work through the insert and delete operations for heaps in this array representation: the textbook gives code implementing INSERT and DELETE for this representation . if we delete a value. we must re-organize the tree so that the `gap' created by deleting is filled. 3. However. if we restrict ourselves to complete trees. they will correspond to the first N positions of the array. } This gets us level-by-level traversal! To see this `amazing' fact.

(see CS2121 lecture). and brackets ( ) to allow users to override these rules. and brackets cannot be used to change this order.Infix. This is the usual way we write expressions. Similarly. operators are evaluated left-to-right and brackets are superfluous. For example. the usual rules for precedence say that we perform multiplication and division before we perform addition and subtraction. Prefix notation (also known as "Polish notation"): + X Y Operators are written before their operands. Postfix and Prefix Infix. and the result of the addition. It is easiest to demonstrate the differences by looking at examples of operators that take two operands. Operators act on the two nearest values on the right. The expressions given above are equivalent to / * A + B C D As for Postfix. the "/" uses the result of the multiplication and the "D". For example. I have again added (totally unnecessary) brackets to make this clear: (/ (* A (+ B C) ) D) Although Prefix "operators are evaluated left-to-right". We can add (totally unnecessary) brackets to make this explicit: ( (A (B C +) *) D /) Thus. and if these values themselves involve computations then this changes the order that the . then multiply the result by A. Operators act on values immediately to the left of them. the "*" uses the two values immediately preceding: "A". the usual rules for associativity say that we perform operations from left to right. The infix expression given above is equivalent to A B C + * D / The order of evaluation of operators is always left-to-right. Postfix and Prefix notations are three different but equivalent ways of writing expressions. Similarly. the "+" above uses the "B" and "C". An expression such as A * ( B + C ) / D is usually taken to mean something like: "First add B and C together. so the multiplication by A is assumed to come before the division by D. Infix notation: X + Y Operators are written in-between their operands. the addition must be performed before the multiplication. they use values to their right. Postfix notation (also known as "Reverse Polish notation"): X Y + Operators are written after their operands. then divide by D to give the final answer. Because the "+" is to the left of the "*" in the example above." Infix notation needs extra information to make the order of evaluation of the operators clear: rules built into the language about operator precedence and associativity.

. it acts on the result of the multiplication. 3. Because Postfix operators use values to their left. A+B We have three possibilities for the positioning of the operator. Completely paranthesize the infix expression according to the order of precedence to specify the order of operation. Faruk Tokdemir. Between the operands A+B which is called Infix notation . any values involving computations will already have been calculated as we go left-to-right. Remove all parantheses Consider the arithmetic operators and their precedence as operators priority ^ highest *. Move each operator to its corresponding right (for postfix) left (for prefix) 3. After the operands AB+ which is called Postfix notation or Reverse Polish notation .lowest  .operators have to be evaluated in. In the example above. Consider the simple arithmetic expression. and so the multiplication has to happen before the division (and similarly the addition has to happen before the multiplication). How to convert from infix to postfix from infix to prefix Arithmetic Expressions Dr. although the division is the first operator on the left. 2. 1. METU 2 General rules for conversion 1. and so the order of evaluation of the operators is not disrupted in the same way as in Prefix expressions. ARITHMETIC EXPRESSIONS One of the most important applications of stacks is the evaluation of arithmetic expressions. Before the operands as +AB which is called Prefix notation or Polish notation. (after the Polish logician Jan Lu Lukasiewicz) 2./ + .

. As most binary tree problems. you want to solve this recursively. The root node’s value appear to be 7 from the binary tree above. About Duplicates: In this solution.3. Hint: A good way to attempt this question is to work backwards. Solution: Let us look at this example tree. 2011 in binary tree Given preorder and inorder traversal of a tree. construct the binary tree.2} The crucial observation to this problem is the tree’s root always coincides with the first element in preorder traversal. Why? Consider the following case: preorder = {7.Construct Binary Tree From Inorder and Preorder/Postorder Traversal April 20. then list down its preorder and inorder traversal.4.11.10.8. 7} inorder = {7.7.10.11} inorder = {4. we will assume that duplicates are not allowed in the binary tree.2. _______7______ / \ __10__ ___2 / \ / 4 3 _8 \ / 1 11 The preorder and inorder traversals for the binary tree above is: preorder = {7. 7 / 7 or 7 \ 7 Clearly.1. This must be true because in preorder traversal you always traverse the root node before its children.8. Approach this question by drawing a binary tree.3.1. 7} We can construct the following trees which are both perfectly valid solutions. there would be ambiguity in constructing the tree if duplicates were allowed.

If you remember. we visit the left subtree first. 1} and {2. left subtree and followed by right subtree. we can solve recursively! . 10. Therefore. 4. 11} respectively. After creating the root node (7). 8. We see a clear recursive pattern from the above observation. the left and right subtree’s postorder traversal must be {10. and followed by the right subtree. 8.We easily find that 7 appears as the 4th index in the inorder sequence. so there would be no ambiguity). Since the left and right subtree are binary trees in their own right. 3. then root node. we construct its left and right subtree from inorder traversal of {4. preorder traversal follows the sequence of root node. 2} respectively. We also need its corresponding preorder traversal which could be found in a similar fashion. (Notice that earlier we assumed that duplicates are not allowed in the tree. Therefore. 3. For inorder traversal. 1} and {11. all elements left of 7 must be in the left subtree and all elements to the right must be in the right subtree.