Tree Data Structures CSC 221
Specialized Trees Binary Tree: A restriction of trees such that the maximum degree of a node is 2. Order of nodes is now relevant May have zero nodes (emtpy tree) Formal Definition: A binary tree is a finite set of nodes that either is empty or consists of a root and two disjoint subtrees called the left subtree and the right subtree.
Properties of Binary Trees Given definition of binary tree, interesting (useful?) properties that hold: Maximum number of nodes on level i is 2 i-1 Maximum number of nodes in a binary tree of depth k is 2 k 1 A binary tree with n nodes could have between log 2 n and n depth/height.
Questions What is the maximum number of nodes in a k-ary tree of height h? For 3 = 1 + 3 + 9 + 27 + 81 For 4 = 1 + 4 + 16 + 64 For k = 1 + k + k 2 + k 3 Sum of geometric series: (k h -1) / (k-1) k = 3, h = 4 = (3 4 1) / (3-1) = 80/2 = 40 Does it hold for 2? (2 h -1) / (2-1) = 2 h -1
Properties of Binary Trees A binary tree with n nodes could have between log 2 n and n depth/height. If completely skewed Only one child per node height n. If complete, 1 + 2 + 4 + 8 are counts we can have on each new level. Label levels starting at 1 Sum after every level i is 2 i -1 (think of all i bits on) Need to find I such that 2 i -1 = n 2 i = n+1 i = log 2 (n+1)
Binary Tree Node class BinaryTree; // forward declaration class BinaryTreeNode friend class BinaryTree; private: char data; BinaryTreeNode* leftchild; BinaryTreeNode* rightchild; };
Binary Tree Class class BinaryTree public: // public member methods private: BinaryTreeNode* root; };
Binary Tree Node A(nother?) with linked node representation: Difficult to find parent OK: Could add a parent pointer link to all nodes if particularly important without substantial changes, but with n (number of nodes) bytes more use of memory If is important, when traversing list maintain a parent pointer (like previous pointer) Recursive algorithms may implicitly keep it for us
Binary Tree Class What are functions of interest? class BinaryTree public: BinaryTree(); // create empty tree BinaryTree(char data, BinaryTree bt1, BinaryTree bt2); //construct a new tree, setting root data to data and links to //other trees bool isempty(); // test whether empty BinaryTree leftchild(); // get left child of *this BinaryTree rightchild(); // get right child of *this char Data(); // return data in root node of *this };
Binary Tree Functions Most operations performed on binary trees require moving through the tree: Visiting nodes Inserting an element Deleting an element Height Useful to have a simple mechanism for moving through trees
Binary Tree Traversal Tree traversal Visit each node in the tree exactly once Perform some operation Print data Add to sum Check for max height A traversal produces a linear ordering of the nodes [the order of visits]
Binary Tree Traversal Treat trees and subtrees in same fashion Traverse in same order Use recursion! Let the following define traversal operations: L => Move left V => Visit [Perform operation print, sum, ] R => Move right
Binary Tree Traversal Six possible methods of traversal: LVR, LRV, VLR, VRL, RVL, RLV Usually, only use three of these, all with left before right: LVR LRV VLR Inorder Postorder Preorder
Binary Tree Traversal Let s trace the traversal functions with examples of expressions (operators and operand) Traversal Name corresponds to order of outputted expression
Binary Tree Traversal + * E * D / C Inorder: LVR A / B * C * D + E Infix expression Visit left child before parent A B
Binary Tree Traversal Inorder implementation: void BinaryTree::inorder() inorder(root); } Void BinaryTree::inorder(BinaryTreeNode* node) if (node) inorder(node->leftchild); cout << node->data; // replace cout with inorder(node->rightchild); //arbitrary processing } }
Binary Tree Traversal + * E * D / C Postorder: LRV A B / C * D * E + Postfix expression Visit left and right child before parent A B
Binary Tree Traversal Postorder implementation: void BinaryTree::postorder() postorder(root); } void BinaryTree::postorder(BinaryTreeNode* node) if (node) postorder(node->leftchild); postorder(node->rightchild); cout << node->data; } }
Binary Tree Traversal + * E * D / C Preorder: VLR + * * / A B C D E Prefix expression Visit parent before either child A B
Binary Tree Traversal Preorder implementation: void BinaryTree::preorder() preorder(root); } Void BinaryTree::preorder(BinaryTreeNode* node) if (node) cout << node->data; preorder(node->leftchild); preorder(node->rightchild); } }