DATA STRUCTURES AND ALGORITHMS LECTURE 13 BINARY TREES IMRAN IHSAN ASSISTANT PROFESSOR AIR UNIVERSITY, ISLAMABAD DEFINITION The arbitrary number of children in general trees is often unnecessary many real-life trees are restricted to two branches Expression trees using binary operators An ancestral tree of an individual, parents, grandparents, etc. Phylogenetic trees Lossless encoding algorithms There are also issues with general trees: There is no natural order between a node and its children 2 Lecture 13 - Binary Trees 1
DEFINITION A binary tree is a restriction where each node has exactly two children: Each child is either empty or another binary tree This restriction allows us to label the children as left and right subtrees We will also refer to the two sub-trees as The left-hand sub-tree, and The right-hand sub-tree 3 DEFINITION Sample variations on binary trees with five nodes: 4 Lecture 13 - Binary Trees 2
DEFINITION A full node is a node where both the left and right sub-trees are non-empty trees Legend: full nodes neither leaf nodes 5 DEFINITION An empty node or a null sub-tree is any location where a new leaf node could be appended 6 Lecture 13 - Binary Trees 3
DEFINITION A full binary tree is where each node is: A full node, or A leaf node These have applications in Expression trees Huffman encoding 7 BINARY NODE CLASS The binary node class is similar to the single node class: #include <algorithm> class Binary_node { protected: Type element; Binary_node *left_tree; Binary_node *right_tree; public: Binary_node( Type const & ); Type retrieve() const; Binary_node *left() const; Binary_node *right() const; bool empty() const; bool is_leaf() const; int size() const; int height() const; void clear(); 8 Lecture 13 - Binary Trees 4
BINARY NODE CLASS CONSTRUCTOR We will usually only construct new leaf nodes Binary_node<Type>::Binary_node( Type const &obj ): element( obj ), left_tree( nullptr ), right_tree( nullptr ) { // Empty constructor 9 BINARY NODE CLASS ACCESSORS The accessors are similar to that of Single_list Type Binary_node<Type>::retrieve() const { return element; Binary_node<Type> *Binary_node<Type>::left() const { return left_tree; Binary_node<Type> *Binary_node<Type>::right() const { return right_tree; 10 Lecture 13 - Binary Trees 5
BINARY NODE CLASS BASIC FUNCTIONALITY Much of the basic functionality is very similar to Simple_tree bool Binary_node<Type>::empty() const { return ( this == nullptr ); bool Binary_node<Type>::is_leaf() const { return!empty() && left()->empty() && right()->empty(); 11 BINARY NODE CLASS SIZE int Binary_node<Type>::size() const { return empty()? 0 : 1 + left()->size() + right()->size(); 12 Lecture 13 - Binary Trees 6
BINARY NODE CLASS HEIGHT int Binary_node<Type>::height() const { return empty()? -1 : 1 + std::max( left()->height(), right()->height() ); 13 BINARY NODE CLASS CLEAR Removing all the nodes in a tree is similarly recursive: void Binary_node<Type>::clear( Binary_node *&ptr_to_this ) { if ( empty() ) { return; left()->clear( left_node ); right()->clear( right_node ); delete this; ptr_to_this = nullptr; 14 Lecture 13 - Binary Trees 7
APPLICATION: EXPRESSION TREES Any basic mathematical expression containing binary operators may be represented using a binary tree For example, 3(4a + b + c) + d/5 + (6 e) 15 APPLICATION: EXPRESSION TREES Observations: Internal nodes store operators Leaf nodes store literals or variables No nodes have just one sub tree The order is not relevant for Addition and multiplication (commutative) Order is relevant for Subtraction and division (non-commutative) It is possible to replace non-commutative operators using the unary negation and inversion: (a/b) = a b -1 (a b) = a + ( b) 16 Lecture 13 - Binary Trees 8
APPLICATION: EXPRESSION TREES A post-order depth-first traversal converts such a tree to the reverse-polish format 3 4 a b c + + d 5 6 e + + 17 APPLICATION: EXPRESSION TREES Humans think in in-order Computers think in post-order: Both operands must be loaded into registers The operation is then called on those registers Most use in-order notation (C, C++, Java, C#, etc.) Necessary to translate in-order into post-order 18 Lecture 13 - Binary Trees 9
FULL VS COMPLETE BINARY TREE A full BT of depth k is a binary tree of depth k having 2 k -1 nodes, k>=0. A binary tree with n nodes and depth k is complete iff its nodes correspond to the nodes numbered from 1 to n in the full binary tree of depth k. Full Binary Tree A Complete Binary Tree A B C B C D E F G D E F G H I H I J K J K J K 19 LABELING NODES Label the nodes 1 through 2 k+1 1. Label by levels from top to bottom. Within a level, label from left to right. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 20 Lecture 13 - Binary Trees 10
NODE NUMBER PROPERTIES Parent of node i is node i / 2, unless i = 1. Node 1 is the root and has no parent. Left child of node i is node 2i, unless 2i > n, where n is the number of nodes. If 2i > n, node i has no left child. 1 Right child of node i is node 2i+1, unless 2i+1 > n, where n is the number of nodes. If 2i+1 > n, node i has no right child. 2 3 4 5 6 7 8 9 10 11 12 13 14 15 21 ARITHMETIC EXPRESSION USING BT inorder traversal A / B * C * D + E infix expression * + E preorder traversal + * * / A B C D E prefix expression * D postorder traversal A B / C * D * E + postfix expression A / B C level order traversal + * E * D / C A B 22 Lecture 13 - Binary Trees 11
INORDER TRAVERSAL (RECURSIVE VERSION) void inorder(ptnode ptr) /* inorder tree traversal */ { if (ptr) { inorder(ptr->left); cout<<ptr->data; indorder(ptr->right); A / B * C * D + E 10 Binary Trees Data Strutures & Algorithms Imran Ihsan - www.imranihsan.com 23 PREORDER TRAVERSAL (RECURSIVE VERSION) void preorder(ptnode ptr) /* preorder tree traversal */ { if (ptr) { cout<<ptr->data; preorder(ptr->left); predorder(ptr->right); + * * / A B C D E 10 Binary Trees Data Strutures & Algorithms Imran Ihsan - www.imranihsan.com 24 Lecture 13 - Binary Trees 12
POSTORDER TRAVERSAL (RECURSIVE VERSION) void postorder(ptnode ptr) /* postorder tree traversal */ { if (ptr) { postorder(ptr->left); postdorder(ptr->right); cout<<ptr->data; A B / C * D * E + 10 Binary Trees Data Strutures & Algorithms Imran Ihsan - www.imranihsan.com 25 LEVELORDER TRAVERSAL (USING QUEUE) void levelorder(ptnode ptr) /* level order tree traversal */ { int front = rear = 0; ptnode queue[max_queue_size]; if (!ptr) return; /* empty queue */ enqueue(front, &rear, ptr); for (;;) { ptr = dequeue(&front, rear); if (ptr) { cout<<ptr->data; if (ptr->left) enqueue(front, &rear, ptr->left); if (ptr->right) 10 Binary Trees Data Strutures & Algorithms enqueue(front, &rear, ptr->right); Imran Ihsan - www.imranihsan.com + * E * D / C A B 26 Lecture 13 - Binary Trees 13
EULER TOUR TRAVERSAL Generic traversal of a binary tree Includes a special cases the preorder, postorder and inorder traversals Walk around the tree and visit each node three times: on the left (preorder) from below (inorder) on the right (postorder) + L R 2 B - 3 2 5 1 10 Binary Trees Data Strutures & Algorithms Imran Ihsan - www.imranihsan.com 27 EULER TOUR TRAVERSAL eulertour(node v) { //perform action for visiting node on the left; if v is internal then eulertour(v->left); //perform action for visiting node from below; if v is internal then eulertour(v->right); //perform action for visiting node on the right; 10 Binary Trees Data Strutures & Algorithms Imran Ihsan - www.imranihsan.com 28 Lecture 13 - Binary Trees 14