THREADED BINARY TREE

Consider the linked representation of a binary tree T, approximately half of the entries in
left pointer field and right pointer field contains NULL elements. This space occupied by
NULL entries can be efficiently utilized to store some kind of valuable information. These
special pointers are called threads, and the binary tree having such pointers is called a
threaded binary tree.
Threads in a binary tree are represented by a dotted line. There are many ways to thread a
binary tree these are—

1. The right NULL pointer of each leaf node can be replaced by a thread to the
successor of that node under in order traversal called a right thread, and the tree will
called a right threaded tree or right threaded binary tree.
2. The left NULL pointer of each node can be replaced by a thread to the predecessor
of that node under in order traversal called left thread, and the tree will called a left
threaded tree.
3. Both left and right NULL pointers can be used to point to predecessor and
successor of that node respectively, under in order traversal. Such a tree is called a
fully threaded tree.

A threaded binary tree where only one thread is used is also known as one way threaded
tree and where both threads are used is also known as two way threaded tree.

Memory Representatin Of Treaded Binayr Tree

In above representation char thread field is as a tag. It will hold 0 for normal right pointer
and 1 for thread.

The ordering relationship amongst a set of values is obtained through use of pointers. Although linked lists require more memory space than arrays ( as they have to store address at each node). they have definite advantages over arrays. However.1 Trees Examples of Tree structure Definition of trees Binary tree Height of tree Tree traversals Finding max Finding sum 2 Trees You have seen that using linked lists you can represent an ordered collection of values without using arrays. we need not restrict ourselves to only linear structures. Insertion and deletion of items can be carried out with out involving considerable movement of data. In this chapter we shall extend the use of pointers to define a non-linear structure to model hierarchical .

files are stored in directories that form a tree. Tree as a data structure • A tree is a data structure that is made of nodes and pointers. such a tree can branch off to mammals. birds. Organization charts: In a company a number of vice presidents report to a president. marine life etc. there would be number of counter moves. much like a linked list. It has many subdirectories and 3 files.relationships. The top level directory represents the root. The repetitive pattern results in what is known a game tree. The subdirectories would have further set of subdirectories. Directory Hierarchies: In computers. Biological classifications: Starting from living being at the root. In such a tree. For each position. we have links moving from an ancestor to a parent. Game Trees: All games which require only mental effort would always have number of possible options at any position of the game. and links moving from the parent to children. Each VP would have a set of general managers. such as a family tree. each GM having his/her own set of specific managers and so on. We have many other examples of tree-structured hierarchies. The difference between them lies in how they are organized: • The top node in the tree is called the root and all .

59.18.32. one child or two children. Thus each node can have no child. The pointers help us to identify whether it is a left child or a right child. 4 • Every node in the tree can have some number of children. Binary Trees 5 Definition: A binary tree is a tree in which each node can have maximum two children. • Child nodes can have links only from a single parent. nor a leaf is called an interior node. • Nodes having no children are called leaves. Consider a set of numbers: 25. • The height of a tree is defined to be the length of the longest path from the root to a leaf in that tree ( including the path to root) • A common example of a tree structure is the binary tree.13. 72. Application of a Binary tree Before we define any formal algorithms. . let us look at one possible application of a binary tree. • Any node higher up than the parent is called an ancestor node. • Any node which is neither a root. Each child node can in turn be the parent node to its children and so on.63.67.other nodes branch off from this one.

Let us see if we can improve the situation by storing the data using a binary tree structure. 59 18 67 13 32 63 72 25 7 With this arrangement any search is taking at most 4 . and less than the values stored in the right-child nodes. Thus if there were n numbers.67. You simply cannot apply binary search on a linked list with O(log n) complexity. So a linear linked structure is not helping us at all. To search for a particular item we have to go through the list.72. What would be the search complexity now? You may be surprised to discover that it is still O(n).32. our search complexity would be O(n).18. You still have to go 6 through each link to locate a particular number. and store these in another linked list.Suppose we store these numbers in individual nodes of a singly linked list. and maybe we have to go to the end of the list as well. Consider the following binary tree where the numbers have been stored in a specific order.63.59.25. The value at any node is more than the values stored in the left-child nodes. Is it because the numbers are not in any particular sequence? Now suppose we order these numbers: 13.

For larger set of numbers. • The level of a node in a binary tree: . if we can come up with a good tree arrangement than the search time can be reduced dramatically.steps. Examples of binary trees: root root 8 • The following are NOT binary trees: 9 Definitions: • tree.The root of the tree has level 0 . root Level 0 Level 1 Level 2 Level 3 10 Full Binary Tree How many nodes? Level 0 : 1 node ( height 1) Level 1: 2 nodes ( height 2) Level 3 : 4 nodes (height 3) Level 3: 8 nodes (height 4) Total number of nodes n = 2h – 1 ( maximum) h = log ( n+1) 45 .The level of any other node in the tree is one more than the level of its parent. then n1 is the parent of n2 and n2 is the left or right child of n1.

24 76 14 32 61 87 8 20 27 37 56 67 81 94 11 Implementation • A binary tree has a natural implementation in linked storage. • Recursive definition of a binary tree: A binary tree is either . A tree is a node with structure that contains more trees. However. A tree is referenced with a pointer to its root. or . left_child data right_child 12 Note the recursive definition of trees. struct tree_node *right_child. Traversal of Binary Trees Linked lists are traversed sequentially from first node to the last node. struct tree_node *left_child.Empty. }.A node (called root) together with two binary trees (called left subtree and the right subtree of the root) • Each node of a binary tree has both left and right subtrees which can be reached with pointers: struct tree_node{ int data. We have actually a tree located at each node of a tree. there is no such natural linear order for .

− With preorder traversal the root node is visited first. .the nodes of a tree. then the root and finally the right subtree. root node. There are three common traversals for binary trees: • Preorder • Inorder • Postorder These names are chosen according to the sequence in which the root node and its children are visited. Different orderings are possible for traversing a binary tree. − With postorder traversal the order is left child. n1 n2 n3 In – order : n2 n1 n3 Pre-order : n1 n2 n3 Post order : n2 n3 n1 14 A tree will typically have more than 3 nodes. Suppose there are only 3 nodes in the tree having the following arrangement: 13 − With inorder traversal the order is left-child. Thus the root is visited in-between visiting the left and right subtrees. root node. right child. left child . right child. right-child − With preorder traversal the order is root node. Every node in the tree is a root for the subtree that it points to. Instead of nodes n2 and n3 there would be subtrees as shown below: − With inorder traversal the order is left subtree.

. p->data). If there is a left child we visit the left subtree (all the nodes) in pre-order fashion starting with that left child . The real job is done by the system on the runtime stack. • As the structure of a binary tree is recursive. void preorder(struct tree_node * p) { if (p !=NULL) { printf(“%d\n”. the traversal algorithms are inherently recursive. Algorithm for Preorder traversal In a preorder traversal. but the real power lies in the recursive formulation. 16 preorder(p->left_child). we first visit the root node.then the nodes in the left subtree are visited followed by the nodes in the right subtrees root Left subtree Right subtree 15 − With postorder traversal the root is visited after both the subtrees have been visited. The function may seem very simplistic. In fact there is a double recursion. If there is a right child then we visit the right subtree in pre-order fashion starting with that right child.(left subtree followed by right subtree. This simplifies coding while it puts a heavy burden on the system. preorder(p->right_child).

inorder(p->right_child). Example: Preorder Traversal : a b c d f g e a(root) b(left) c d f g e (right) Algorithm for Inorder traversal root a bc de fg 17 In the inorder traversal. then we visit the root node and then its right subtree.} } Take a tree of say height 3 with maybe 6 nodes and try to run the above recursion to find out the actual order of printing the nodes. p->data). printf(“%d\n”. void inorder(struct tree_node *p) { if (p !=NULL) { inorder(p->left_child). we first visit its left subtree (all the nodes) . } } Inorder: b a f d g c e b(left) a(root) f d g c e(right) Algorithm for Postorder traversal root a bc .

max. rightmax. leftmax. max = -1 //assume all values in the tree are positive integers if (p != NULL) { node_data = p -> data. printf(“%d\n”. we first visit its left subtree (all the nodes) and then visit its right subtree ( all the nodes) and then finally we visit the root node. p->data). void postorder(struct tree_node *p) { if (p !=NULL) { postorder(p->left_child). postorder(p->right_child). leftmax = findMax(p -> left_child). } } Example: Postorder: b f g d e c a b(left) root a bc de fg 19 f g d e c(right) a(root) 20 Finding Maximum value in a given tree p int findMax (struct tree_node *p) { int node_data.de fg 18 In a postorder traversal. .

21 node_value = 45 leftmax = 24 (max of 24.12. -1. -1 ) max = max of 45.rightmax = findMax(p->right_child). -1. rightmax) = 76 24 76 14 32 45 23 . -1 ) rightmax = 76 (max of 76. if (node_data > max) max = node_data. 76 = 76 24 45 76 22 max of left subtree leftmax = max ( 24. //find the largest of the tree values.32) = 24 rightmax = 76 max of tree = max (45. if (leftmax > rightmax) max = leftmax. leftmax. 24. } return max. else max = rightmax.

} 24 . add to the value of the current node. else return 0.Finding sum of values of all the nodes of a tree To find the sum. int sum(struct tree_node *p) { if ( p!= NULL) return(p->data + sum(p->left_child) + sum(p->right_child)). the sum of values of all nodes of left subtree and the sum of values of all nodes in right subtree.

A single- node binary tree has height 0. Note that a balance factor of -1 means that the subtree is left-heavy. for an AVL tree is that it is a binary search tree in which each node has a balance factor of -1.AVL Trees The Concept These are self-adjusting. in the following AVL tree. that is. ordinary binary search trees have a bad worst case. note that the root node with balance factor +1 has a right subtree of height 1 more than the height of the left subtree. An equivalent definition. The balance factor of a node is the height of its right subtree minus the height of its left subtree. essentially more of a linear list. the difference in the heights of its two subtrees is at most 1. AVL trees overcome this problem. As another example. and an empty binary tree has height -1. and a balance factor of +1 means that the subtree is right-heavy. with Theta(n) height and thus Theta(n) worst case insertion and lookup times. height-balanced binary search trees and are named after the inventors: Adelson-Velskii and Landis. 7 / \ 3 12 / / \ 2 10 20 / \ 9 11 An AVL tree is a binary search tree in which every node is height balanced. A balanced binary search tree has Theta(lg n) height and hence Theta(lg n) worst case lookup and insertion times. When sorted data is inserted. (The balance factors are shown at the top of each node. the following binary tree has height 3. Definitions The height of a binary tree is the maximum path length from the root to a leaf. 0. For example.) +1 30 / \ . the binary search tree is very unbalanced. or +1. then. However.

Consider the following example. Hence it should have Theta(lg n) height (it does . a new item is inserted just as in a binary search tree. There are three main cases to consider when inserting a new node. An AVL tree does not have a bad worst case. No change is needed at this node. Case 1: A node with balance factor 0 changes to +1 or -1 when a new node is inserted below it. like a binary search tree which can become very unbalanced and give Theta(n) worst case lookup and insertion times. The following binary search tree is not an AVL tree. Note that the item always goes into a new leaf. Note that after an insertion one only needs to check the balances along the path from the new leaf to the root. -1 0 22 62 / / \ 0 +1 -1 5 44 95 \ / 0 0 51 77 The idea is that an AVL tree is close to being completely balanced. 0 .always) and so have Theta(lg n) worst case insertion and lookup times. -1 100 / \ -2 -1 70 150 / \ / \ +1 0 +1 0 30 80 130 180 / \ \ 0 -1 0 10 40 140 / 0 36 Inserting a New Item Initially. Notice the balance factor of -2 at node 70. The tree is then readjusted as needed in order to maintain it as an AVL tree.

Consider the following example. -1 40 / \ +1 0 20 50 / \ / \ 0 0 0 0 10 30 45 70 / \ 0 0 22 32 After inserting 60 we get: .) No change is needed at this node. 40 / \ +1 0 20 50 \ / \ 0 0 0 30 45 70 After inserting 60 we get: +1 40 / \ +1 +1 20 50 \ / \ 0 0 -1 30 45 70 / 0 60 Case 2: A node with balance factor -1 changes to 0 when a new node is inserted in its right subtree. (Similarly for +1 changing to 0 when inserting in the left subtree.

that the mirror image situation is also included under subcase A. Note that inserting X makes P have a balance factor of -2 and LC have a balance factor of -1. Note that rotations do not mess up the order of the nodes given in an inorder traversal. The -2 must be fixed. Subcase A: This consists of the following situation.an example of case 1 20 50 / \ / \ 0 0 0 -1 <-. too. The tree is restored to an AVL tree by using a rotation. and X is the new node added.an example of case 1 10 30 45 70 / \ / 0 0 0 22 32 60 Case 3: A node with balance factor -1 changes to -2 when a new node is inserted in its left subtree. (Similarly for +1 changing to +2 when inserting in the right subtree. (Note. LC is P's left child.the -1 changed to a 0 (case 2) 40 / \ +1 +1 <-. This is very important since it means that we still have a legitimate binary search tree. 0 <-. This is accomplished by doing a right rotation at P. where P denotes the parent of the subtree being examined.) (rest of tree) | -2 P / \ -1 sub LC tree of / \ height n sub sub tree tree of of height height n n / X .) Change is needed at this node.

-1 80 / \ -1 -1 30 100 / \ / 0 0 0 15 40 90 / \ 0 0 10 20 We then insert 5 and then check the balance factors from the new leaf up toward the root. (rest of tree) | 0 LC / \ sub P tree of / \ height n sub sub / tree tree X of of height height n n Consider the following more detailed example that illustrates subcase A.) This gives the following picture.The fix is to use a single right rotation at node P. (In the mirror image case a single left rotation is used at P.) -2 80 / \ -2 -1 30 100 / \ / -1 0 0 . (Always check from the bottom up.

The fix is to use a single left rotation at P. See if you can draw a picture of the following after the left rotation at P. Then draw a picture of a particular example that fits our general picture below and fix it with a left rotation. (Since we work bottom up. 15 40 90 / \ -1 0 10 20 / 0 5 This reveals a balance factor of -2 at node 30 that must be fixed. (rest of tree) | +2 P / \ sub +1 tree RC of height / \ n sub sub tree tree of of height height n n \ X . The other -2 problem will go away once we fix the problem at 30. The following is a general illustration of this situation.) The fix is accomplished with a right rotation at node 30. we reach the -2 at 30 first. -1 80 / \ 0 -1 15 100 / \ / -1 0 0 10 30 90 / / \ 0 0 0 5 20 40 Recall that the mirror image situation is also included under subcase A. leading to the following picture.

LC is P's left child. Note that inserting X makes P have a balance factor of -2 and LC have a balance factor of +1. A double right rotation at P consists of a single left rotation at LC followed by a single right rotation at P. NP is the node that will be the new parent. The -2 must be fixed. then a new picture for the result of the right rotation at P).) In the above picture. (In the mirror image case a double left rotation is used at P. (rest of tree) | -2 P / \ -2 sub NP tree of / \ height n 0 sub LC tree / \ n-1 sub sub .Subcase B: This consists of the following situation. the double rotation gives the following (where we first show the result of the left rotation at LC. where P denotes the parent of the subtree being examined. This consists of a single right rotation at the right child RC followed by a single left rotation at P. X might be added to either of the subtrees of height n-1. This is accomplished by doing a double rotation at P (explained below). (Note that the mirror image situation is also included under subcase B.) (rest of tree) | -2 P / \ +1 sub LC tree of / \ height n sub -1 tree NP of / \ height sub sub n tree tree n-1 n-1 / X The fix is to use a double right rotation at node P. and X is the new node added.

(rest of tree) | 0 NP / \ 0 +1 LC P / \ / \ sub sub sub sub tree tree tree tree of n-1 n-1 of height / height n X n Consider the following concrete example of subcase B. we get a problem. as seen below. a balance factor of -2 at the root node. -2 80 / \ +1 0 30 100 / \ / \ . tree tree of n-1 height / n X Finally we have the following picture after doing the right rotation at P. -1 80 / \ 0 0 30 100 / \ / \ -1 0 0 0 20 50 90 120 / / \ 0 0 0 10 40 60 After inserting 55.

-1 +1 0 0 20 50 90 120 / / \ 0 0 -1 10 40 60 / 0 55 As discussed above. the right rotation at 80 restores the binary search tree to be an AVL tree. First we do a single left rotation at 30. 0 50 / \ -1 0 30 80 / \ / \ -1 0 -1 0 20 40 60 100 / / / \ 0 0 0 0 10 55 90 120 Example Program • itemtype. -2 80 / \ -1 0 50 100 / \ / \ -1 -1 0 0 30 60 90 120 / \ / -1 0 0 20 40 55 / 0 10 Finally. This gives the following picture. The resulting picture is shown below.h . this calls for a double rotation.

cpp • bstree. So a pointer to one type of node is not of . that AVLClass is named as a friend of BSTClass so that it can have direct access to the private data fields of the latter class. (Public fields are also possible but rarely used since they violate the principle of information hiding. One type of node is derived by inheritance from the other and is almost the same.cpp • avlnode. a destructor. instead of the usual private fields. AVLNodeClass is derived by public inheritance from BSTNodeClass. Since CopySubtree expects a pointer to an AVLNodeClass node. The class AVLClass is derived by public inheritance from the class BSTClass. This makes the coding simpler. For example. In the BSTNodeClass note that the data fields are protected fields. The public functions provided are a constructor. There are no new data fields added in the derived class. such as from our application program in the main function. Empty. an overloaded assignment operator.cpp • avltest. but to the compiler they are different types.h • bstree. but is not accessible elsewhere. uses a print routine to see that the AVL tree is correct. The AVLNodeClass only needs to add one data field to the inherited ones: a field to hold the balance number for this node. as it is much easier to do so. Find. and a function to insert a new item. and Print.) A protected field is directly accessible in a publicly derived class. This means that we do not need to make AVLNodeClass a friend of BSTNodeClass in order for the derived class to have direct access to the data fields.h • bstnode.h • avlnode. Note.cpp • avltree.cpp This example program inserts some characters into an AVL tree. we need the cast. a BSTNodeClass node. a copy constructor. this allows considerable code reuse. the CopySubtree function in AVLClass contains: NewLeftPtr = CopySubtree(reinterpret_cast <AVLNodePtr> (Current->Left)) This is needed because the data field Left is a pointer to the wrong type of node. The following public functions are inherited from BSTClass and hence are also available: NumItems. the Find function. Since we have already implemented binary search trees and AVL trees are a form of specialized binary search tree. etc.h • avltree. Note that the Print function prints the binary search tree sideways. too. One messy feature of the above example is that in many places a cast is required so that a pointer to a BSTNodeClass node is seen as a pointer to an AVLNodeClass node. • bstnode. AVLClass also has numerous private functions to carry out the various rotations and the like. and tries out other features such as the copy constructor.

such as: Result = reinterpret_cast <AVLNodePtr> (AVLTreeA. . but here it does add the nuisance of a cast. Code reuse helps a lot. Our Find function returns a pointer to the wrong type of node.Find('E')) This one is needed since we are using the inherited Find function on an AVL tree. which belongs to the derived class.the same type as a pointer to the other type of node. Similar casts occur in the application code found in the main function. so we fix it up with the cast. Hence we need the cast.