• Tree • Binary Tree Arrays and Linked List ARRAYS 1. Good Data structure for Searching algorithms. 2. Disadvantage : Insertion and Deletion of Elements require Data movements(Time Consuming) LINKED LIST 1. It allows quick insertion and deletion of elements. 2. Searching is difficult. A Sequential traversal from the beginning of the list is required to search for an element until it is found or up to the end of the list What is a Tree? A tree combines the advantages of an array and a linked list. (Ie ) We can search quickly as well as Insert and Delete Elements quickly Trees are Non Linear Data Structures ( They are not Sequential as an array,stack etc….) Definition A Tree is a data structure that represents hierarchical relationships between individual data items Level 0 DAD Tree Root SON DAUGHTER SON (Which has no parents) Level 1 Branch/ edge GS1 GS2 GS3 ( Connectors between nodes) Level 2 Tree with n nodes will have n-1 edges Path : Sequence of Consecutive Edges Height : One More than the Last Level Siblings / children ( which has parents) Leaf Node / External ( No children) Binary Tree Definition: It is a tree in which every node has two children ( left child and right child) A B D C E F G H I Binary Tree Node is defined as follows: struct node { int data; node *left; node *right; } //Data field //A reference to the node’s left child. //A reference to the node’s right child. Traversing : Means visiting all the nodes of the tree, in some specific order for processing. There are THREE ways of Traversing a Tree 1. PREODER TRAVERSAL 2. INORDER TRAVERSAL 3. POSTORDER TRAVERSAL Traversing PreOrder Traversal : (VLR) + - * • Visit the current node. / C A B Traverse the left sub-tree of the current node. E Traverse the right sub-tree of the current node. F +-AB*C/EF void preOrder(node *n) { if (n != NULL){ cout<<n->data<<endl; preOrder(n->left); preOrder(n->right); }} //Display the current node //Traverse left sub-tree //Traverse right sub-tree preOrder(root); Traversing InOrder Traversal : (LVR) + - * Traverse the left sub-tree of the currentAnode. / C B Visit the current node. E Traverse the right sub-tree of the current node. F A - B + C* E / F void preOrder(node *n) { if (n != NULL){ InOrder(n->left); cout<<n->data<<endl; InOrder(n->right); }} //Traverse left sub-tree //Display the current node //Traverse right sub-tree preOrder(root); Traversing PostOrder Traversal : (LRV) + - * Traverse the left sub-tree of the currentAnode. / C B Traverse the right sub-tree of the current node. E Visit the current node. F AB-CEF/*+ void postOrder(node *n) { if (n != NULL){ postOrder(n->left); postOrder(n->right); cout<<n->data<<endl; }} //Traverse left sub-tree //Traverse right sub-tree //Display the current node preOrder(root); Application • A binary tree can be used to represent an expression – that involves only binary arithmetic operators +, -, /, and *. – The root node holds an operator, and each of its sub-trees represents either a variable (operand), or another expression. A*(B+C) * Traversing : inorder : preorder : postorder : A*B+C *A+BC ( prefix ) ABC+*, (postfix). A + B C BINARY SEARCH TREE A binary search tree is a 1) binary tree, 2) with the additional condition that if a node contains a value k, then every node in its left sub-tree contains a value less than k, and every node in its right sub-tree contains a value greater than or equal to k. An important consequence of the above property is that an inorder traversal on a binary tree will always visit the vertices of the tree in ascending order. The important operations on a binary search tree are: 1.Searching for a value 2. Inserting a node 3. Deleting a node 4. Finding the minimum or maximum of values stored in the tree. Definition INORDER SUCCESSOR: If a node has a right sub-tree, its inorder successor is the last left node on this right sub-tree. The node containing the value 40 is called the inorder successor of the node containing the value 35. 60 It is useful when deleting a node 85 35 27 15 30 42 40 51 SEARCHING in Binary Tree Start from ROOT NODE. Compare the Search Value with the data in the NODE. Possibilities: a. If “=“ Value has been Found/ Search is terminated. b. If search key “>” than the data of the current node, the search proceeds with the right child as the new current node. c. If the search key is”<“ than the data of the current node, the search proceeds with the left child as the new current node. d. If the current node is NULL, the search is terminated as unsuccessful. Algorithm void search(int val,node *root) { node *s = root; int flag=1; while ((s->data != val)&&(flag)){ if(val < s->data) s = s->left; else s = s->right; if(s == NULL) flag=0; } if (flag) cout<<"found!"; else cout<<"not found";} //start search at root //examine current data //go to left child //go to right child //no node! 60 35 27 15 30 85 42 40 51 60 INSERTING A NEW NODE 35 27 85 42 Search Until “NULL” is encountered. 15 40 30 Insert the NEW NODE and connected to its parent. void Insert(int val,node *root) { node *n,*parent,*s; n = new node; //create a new node; n->data = val; //store value. n->left=NULL; n->right=NULL; s = root; //start search at root int flag=1; while(flag){ //tree traversal parent = s; if(val < s->data){ //go to left child s = s->left; 51 if(s == NULL){ //if null, insert new node parent->left = n; flag=0; } // end 2nd if } // end 1st if else { //go to right child s = s->right; if(s == NULL){ //if null, insert new node parent->right = n; flag=0; } } //end else } //end while } //end insert DELETING A NODE Deleting a node is the most complicated operation required for binary search tree. There are three cases to consider: a. b. c. The node to be deleted is a leaf (has no children). The node to be deleted has one child. The node to be deleted has two children. 5 null 4 null 3 6 To delete a node with two children 60 40 35 27 15 85 42 30 70 40 41 51 41 65 92 80 Algorithm void Remove(int val,node *root) { node *s=root,*temp=s,*n,*pn; while((s->data!=val)&&(s!=NULL)) { temp=s; if (val<s->data) s=s->left; else s=s->right; } if (s!=NULL) {if ((s->left==NULL)&&(s-> right== NULL )) {if (temp->left->data==val) temp->left=NULL; else temp->right=NULL; delete s; } //LOCATE THE NODE //AFTER LOCATING //LEAF NODE //TEMP - PARENT Algorithm if ((s->left==NULL) || (s->right==NULL)) //the node to be deleted has //only one child { if (temp->left->data==val) { if (s->right!=NULL) temp->left=s->right; 5 else temp->left=s->left; } 4null 6 else 3 { if (s->right!=NULL) temp->right=s->right; else temp->right=s->left; } } if ((s->left!=NULL)&&(s->right!=NULL)) {// find the inorder successor of node s 60 Algorithm 40 27 42 n=s->right; while(n->left!=NULL) // FIND THE INORDER SUCCESSOR 15 30 41 { pn=n; n=n->left; } 51 s->data=n->data; // replace the data of the node to be deleted with the data of its in-order successor if (n->right!=NULL) //PUT THE RIGHT CHILD VALUE IN INORDER PLACE { n->data=n->right->data; delete n->right; n->right=NULL; } else { pn->left=NULL; delete n; } // IF NO RIGHT CHILD THEN PARENT LINK IS NULL } }else cout<<"element doesn't exist"<<endl; // COULD NOT FIND THE NODE } COMPUTING THE MINIMUM AND MAXIMUM VALUES 60 35 27 15 85 42 30 70 40 51 65 92 80 41 int Minimum (node *root) { node *s = root; node * last; while (s != NULL) { last = s; s = s->left; } return last->data; } int Maximum(node *root) { node *s = root; node * last; while (s != NULL) { last = s; s = s->right; } return last->data; }