
Binary Trees Computer Science and Engineering
Introduction • We studied linked list is a dynamic linear data structure. • It is dynamic since it supports efficient addition and deletion of items. • It is linear since it is sequential and each element in it has exactly one successor. • A tree is nonlinear data structure. • Each element may have more than one successor. • Can be static or dynamic.
Topics for Discussion • Elements of a tree • Examples of trees • Binary Tree Definition • Types of binary trees • Contiguous (static) representation • Dynamic representation
Terminology • Trees are used to represent relationships: items in a tree are referred to as nodes and the lines connecting the nodes that express the hierarchical relationship are referred to as edges. • The edges in a tree are directed. • Trees are hierarchical which means that a parent-child relationship exist between the nodes in the tree. • Each node has at most one parent. The node with no parents is the root node. • The nodes that have no successors (no children nodes) are known as leaf nodes. • Lets look at some examples and identify the various elements.
Examples • Family ancestor tree • Directory of files organization in your computer system • Parse tree • Languages are defined using grammar • Grammars are specified using rules or syntax • Syntax is expressed using a notation called Backaus-Naur Form (BNF) (John Backus and Peter Naur) • Expression trees • Game trees
An Ancester Tree (From Greek mythology) Gaea Cronus Phoebe Ocean Zeus Poseidon Demeter Pluto Leto ……… Apollo
BNF for a Language • BNF notation includes nonterminals and terminals. • Terminals are literals or particular symbols. • Nonterminals are general expressions that can be substituted with terminals and nonterminals. Grammar rules specify the definition of a nonterminal. Nonterminals are enclosed with angle brackets <nonterminal> • Symbols used in construction include ::= (defines), | (or) and other common operators.
BNF for a Java Statement <statement> ::= <selection-stmt> | <other-stmt> <selection-stmt> ::= if (<expr>) <statement> else <statement> <expr>::= <relational-expr>|<assign-expr>|<identifier> <relational-expr> ::= <expr> <rel-op> <expr> <assign-expr> ::= <expr> = <expr>
Parse tree <statement> <selection-stmt> if ( <expr> ) <statement> else <statement> … <expr> <relational-expr> <expr> <expr> <rel-op> …. A major task of the compiler is to construct a parse tree from the input program and verify it is correct. <identifier> <identifier> < b a
Expression tree + A + B + C * D + <left><root><right> (in-order expression) <root><left><right> (pre-order expression> <left><right><root> (post-order expression) * A B C D Single representation; Multiple views
X X X X X X X X X X X X Game Tree …… X X X …. … X X X X X X
Binary Tree • A binary tree can be defined recursively as follows. It is either • empty, or • consists of a root node together with left and right trees, both of which are binary trees.
Binary Tree NonEmpty Empty NullObject (pattern) Singleton (pattern)
Characteristics of trees • A path is a sequence of nodes n1, n2, ..., nk such that node ni is the parent of node ni+1 for all 1 <= i <= k. • The length of a path is the number of edges on the path. • The height of a node is the length of the longest path from the node to a leaf. • The height of tree is the height of its root. • The level of a node is the length of the path from the root to the node.
Full Binary Tree • A full binary tree is a tree in which each node has exactly zero or two non-empty children. All leaves are at the same level. • A complete binary tree in which all the leaf nodes are in level n or n-1 and all leaves on the level n are filled from left to right. • There are some interesting properties that arise out of this definition. • Lets look at some examples to illustrate the various definitions.
Example root Level 0 Level 1 internal node Height of the tree:3 leaf
Contiguous Representation for complete binary tree 1 2 3 5 4 6 7 8
Complete binary tree (contd.) • Number the N nodes sequentially, from 1.. N, starting with the root , level by level from left to right. • Parent(n) = floor(n/2) for n>1 • Left child(n) = 2n (if 2n <= N, else no left child) • Right child(n) = 2n+1 (if 2n+1 <= N, else no right child) • The node number of children and parent can be calculated for a given node n.
Contiguous representation • By placing the N nodes in a contiguous sequence we can use simple arithmetic relationships to process the nodes. This will eliminate storage for the pointers to sub trees. Root object 0 1 2 3 4 5 6 8 7
Array Representation • Refer to the array in slide 21 which represents the complete binary tree in slide 19; • Array index 1 has the root object, 2 and 3 the left and right sub tree of root object respectively and so on. • The storage needed for the pointers to the left and right sub tree for each node is eliminated; • But the location need to be calculated every time a node is accessed. Trade off is between the storage need for the pointers and extra execution time incurred for computing the location.
Linked Representation • In its simplest form class BTree{ Object obj; BTree left; BTree right; //constructor get, set methods //public Object acceptVisitor(…) //for all other //operations }
BTreeInterface Object getData( ) Object getLeft( ) Object getRight( ) void setData( ) void setLeft( ) void setRight( ) BTree Linked Representation • Simple interface/implementation /application • Addition of a visitor (Visitor Pattern) • State-based implementation
Methods for Tree class • Trees are very widely used in many applications. • It is simply impossible and impractical to think of all the applications to decide the operations to implement in a tree class. Many may not be known apriori. • Even if you implement all possible operations you can think of, only a small subset may be used by a given application. For example, preorder traversal may not be needed for game tree application. • Solution: add operations to the tree class depending on the application. • This requires recompilation. • Another solution is to use a Visitor pattern.
Visitor Pattern • Visitor Pattern: elegant solution that allows for future addition of an operation to a class. The operation need not be known to a class at the time of its implementation. • Requirements: • Class (say, AClass) should have a method to accept visitors (say, acceptVisitor). That is, AClass and its subclasses receive visitors thru’ this method. • Visitor super class (say, interface Visitor) that specifies the signatures for the methods (operations) to be implemented by concrete visitors, one operation per concrete subclass of AClass. • acceptVisitor method should be passed an object reference to the visitor and place holders for input and output data (objects). This method is independent of implementation/name of the concrete visitors. • Concrete visitor has implementations of the operations specified in the interface Visitor.
Using a Visitor • In an application: • Instantiate an object, say host, of concrete class of AClass. • Btree host = new Btree(); • Instantiate an object, aVisitor, of concrete visitor class. • Visitor aVisitor = new WeightVisitor(); • To carry out the operation defined in the visitor, make the “host” class “accept” the “visitor” through the acceptVisitor method. • Object result = host.acceptVisitor(aVisitor, inputObj);
Visitor Pattern: UML Diagram …. . ……
State-based BTree • Two states: EmptyTree and NonEmptyTree • Abstract class unifying the states: AState • SBTreeInterface specifying signatures for the binary tree including acceptVisitor() • SBTree concrete class that has a acceptVisitor • Implementation of basic operations (set, get, etc.) • Implementation of concrete visitors for various operations.