You are on page 1of 21

DATA STRUCTURE

TREE
Dr
Mourad Raafat
Definition

A tree T is a set of nodes storing elements such


that the nodes have a parent-child relationship
that satisfies the following properties:
• If T is nonempty, it has a special node, called the root
of T, that has no parent.
• Each node v of T different from the root has a unique
parent node w; every node with parent w is a child of w.
 Two nodes that are children of the same parent are siblings.
 A node v is external if v has no children.
 External nodes are also known as leaves.

 A node v is internal if it has one or more children.


 A node has at most one parent, but possibly
many ancestor nodes, such as the parent's
parent.
 For example, in Figure 8.3, cs252/ is an ancestor of papers/,

 v is a descendant of a node u if u is an
ancestor of v.
 pr3 is a descendant of cs016/.

 The subtree of T rooted at a node v is the


tree consisting of all the descendants of v in
T (including v itself).
 subtree rooted at cs016/ consists of the nodes cs016/, grades,
homeworks/, programs/, hw1, hw2, hw3, pr1, pr2, and pr3.
 An edge of tree T is a pair of nodes
(u,v) such that u is the parent of v,
or vice versa.
 A path of T is a sequence of nodes
such that any two consecutive nodes
in the sequence form an edge.
For example, the tree in Figure 8.3 contains the path (cs252/,
projects/, demos/, market).
Depth and Height

 The depth of p is the number of ancestors


of p, excluding p itself.
 For example, in the tree of Figure 8.2, the node storing
International has depth 2.

 The depth of p can also be recursively


defined as follows:
• If p is the root, then the depth of p is 0.
• Otherwise, the depth of p is one plus the depth of the parent of p.

 def depth(self, p):


if self.is root(p):
return 0
else:
return 1 + self.depth(self.parent(p))
The height of a position p in a tree T is also
defined recursively:
• If p is a leaf, then the height of p is 0.
• Otherwise, the height of p is one more than the maximum of
the heights of p’s children.
The height of a nonempty tree T is the height of the root
of T. For example, the tree of Figure 8.2 has height 4.
Binary Tree

 A binary tree is an ordered tree


with the following properties:
1. Every node has at most two children.
2. Each child node is labeled as being
either a left child or a right child.
3. A left child precedes a right child in the
order of children of a node.
Types of binary tree
 Full or proper BT
 strictly has zero or two children

 Complete BT
 every level complete
 May be complete left side

 Perfect BT
 All nodes have two children except leaves also same level
 A binary tree representing an arithmetic expression. This tree represents the expression ((((3 +1)×3)/((9
−5)+2))−((3×(7−4)) +6)). The value associated with the internal node labeled “/” is 2.
Motivation for BT
1- If we have to represent the data in a linked structure, i.e., linked list, (because we
cannot anticipate the maximum number of elements), while keeping the search fast.
Notice that: this idea is immediate after our analysis to the binary search in arrays.

2- Building Expression Trees (has great importance in syntactical analysis and parsing),
along with the validity of expressions
+ log !

a b b n
a+b log b n!

a 

b c
a+bc 12
Before ADT and coding, How to traverse a BT? More motivations and benefits

There was no problem for traversing a linear structure like a list. For a BT, at each node
V having left and right subtrees L and R (respectively) we can do the following visiting:

VLR VRL LVR LRV RVL RLV


Preorder Inorder Postorder

The standards are Pre, In, and Post order. In the three of them, L precedes R; then V is
before them (Pre) or in between (In) or after them (Post).

Example: +
The Polish Forms (Ch 12) are
Preorder: +ab related to these orders.
Inorder: a+b b Preorder  Prefix
a
Postorder: ab+ Inorder  Infix
a+b Postorder Postfix

+
Example:
Also notice the strong
Preorder: +abc a  connection between these
Inorder: a+bc traversal modes on a hand
Postorder: abc+ and recursion and stacks on
b c
the other hand. 13
a+bc
Before ADT and coding, How to traverse a BT? More motivations and benefits

Notice that:
For a BT produced by binary search, the Inorder traversal produces sorted elements.
5

2 8

1 3 6 9

F F F 4 F 7 F 10

F F F F F F

1 2 3 4 5 6 7 8 9 10

Now, we have enough motivation for having BTs as data structures. Let us define
the ADT and start coding as linked implementation.

14
Definition: A Binary Tree ADT is either empty, or it consists of a node (vertex)
called the root together with two binary trees called the left subtree and the right
subtree of the root. This is together with the following operations:

1. Create the tree, leaving it empty.


2. Determine whether the tree is empty or not
3. Determine whether the tree is full or not
4. Find the size of the tree.
5. Traverse the tree, visiting each entry
6. Clear the tree to make it empty

We will define the next operations for a special type of BT, i.e., Binary Search
Trees (which will be defined later).
7. Insert a new entry (we have to define where)
8. Delete an entry (we have to define from where)
9. Search for an element.
10. (Any other operation to be defined later).

15
/*Tree.h*/ Linked Implementation
#include "Global.h“

typedef struct treenode{ T


TreeEntry entry;
struct treenode *left, *right;
}TreeNode;
left entry right
typedef TreeNode * Tree;//Book def.

void CreateTree (Tree *);


void ClearTree (Tree *);
int TreeSize (Tree *);
Int TreeDepth (Tree *);
void Preorder (Tree *, void (*)(TreeEntry));
void Inorder (Tree *, void (*)(TreeEntry));
void Postorder (Tree *, void (*)(TreeEntry));

16
void CreateTree(Tree *pt){ pt t
*pt=NULL;
}
entry
}

int TreeEmpty(Tree *pt){ entry


return (!*pt);
}
entry
//User level
int TreeFull(Tree *pt){ Tree t;
return 0; CreateTree(&t);
}

17
//Pre: Tree has been created and intialized.
pt t
//Post: Inorder traversal.
void InorderRec(Tree *pt, void(*pvisit)(TreeEntry)){
if (*pt){ entry
InorderRec(&(*pt)->left, pvisit);
(*pvisit)((*pt)->entry);
InorderRec(&(*pt)->right, pvisit); entry
}
}
Notice that, we pass a pointer to the tree to entry
be consistent with other functions.
//User level
Tree t;
InorderRec(&t, &Display)

18
How to write the previous function iteratively?
void Inorder(Tree *pt, void (* pvisit)(TreeEntry)){
Stack s;
void *p=(void *)(*pt);
/* p will be Pushed in the stack; we do not define it TreeNode *
to avoid modifying Stack.h to include Tree.h*/
if(p){ pt t 
p
CreateStack(&s); 
do{
while(p){ entry
Push(p, &s);
p=(void *)(((TreeNode *)p)->left); entry
}
if(!StackEmpty(&s)){
//This is redundant check; always 1 (prove) entry
Pop(&p, &s);
(*pvisit) (((TreeNode *)p)->entry);
p=(void *)(((TreeNode *)p)->right); pt
}
}while(!StackEmpty(&s) || p); T 
} root size depth
}
void Inorder2(Tree2 *pt, void (* pvisit)(TreeEntry)){
void *p=(void *)(pt->root);//The only change 19
}
pt t

void ClearTreeRec(Tree *pt){


entry
if (*pt){
ClearTreeRec(&(*pt)->left);
ClearTreeRec(&(*pt)->right); entry
free(*pt);
*pt=NULL;
}
entry
} //User level
Tree t;
ClearTreeRec(&t);

20
void ClearTreeRec(Tree *pt){ pt t
if (*pt){
ClearTreeRec(&(*pt)->left);
ClearTreeRec(&(*pt)->right); entry
free(*pt);
*pt=NULL;
} entry
}
void ClearTreeRecAux(Tree *pt){
if (*pt){ entry
ClearTreeRecAux(&(*pt)->left);
ClearTreeRecAux(&(*pt)->right);
free(*pt);
}
}//of course, this is not provided for the user.
It is very smart to notice that (as was noticed by some students during the lecture)
ClearTreeRecAux is faster than ClearTreeRec because it saves the step *pt=NULL in
each recursive call. However it does not set the tree to NULL at the end. We can rewrite a faster
version of ClearTreeRec as:

void ClearTreeRec(Tree *pt){


ClearTreeRecAux(pt);
*pt=NULL;
} 21

You might also like