Data Structures  
Lecture 07: Trees  
Edirlei Soares de Lima  
<edirlei.lima@universidadeeuropeia.pt>  
Trees  
•
A tree data structure allows data to be organized hierarchically.  
–
Examples: file directories, arithmetic expressions, route planning...  
Trees  
•
A tree comprises a set of nodes, such that:  
–
There is a node r, called root, with zero or more subtrees, whose roots  
are linked to r;  
–
–
–
The root nodes of these subtrees are the children of r;  
The inner nodes of the tree are the nodes with children;  
The leaves (or outer nodes) of the tree are the nodes without children;  
root  
subtrees  
Trees  
•
Tree structure  
public class TreeNode<T> : IComparable  
{
private T data;  
private LinkedList<TreeNode<T>> children;  
.
..  
root  
level  
height  
leaves  
Binary Trees  
•
A binary tree is a tree where each node has zero, one or two  
children;  
public class BTreeNode<T>  
{
private T data;  
private BTreeNode<T> left;  
private BTreeNode<T> right;  
...  
}
Binary Trees  
•
Example: a binary tree can be used to represent  
arithmetic expressions:  
–
–
Leaf nodes represent operands;  
Internal nodes operators;  
–
Example: (3+6)*(4-1)+5  
Binary Trees  
Binary Tree – Structure  
public class BTreeNode<T>{  
private T data;  
private BTreeNode<T> left;  
private BTreeNode<T> right;  
public BTreeNode<T> Left{  
get { return left; }  
set { left = value; }  
}
Data  
public BTreeNode<T> Right{  
get { return right; }  
set { right = value; }  
}
Left  
Right  
public T Data{  
get { return data; }  
set { data = value; }  
}
}
Binary Tree  
•
Basic operations:  
–
–
–
Create: creates a node.  
IsEmpty: returns true if the tree is empty.  
Traverse: iterates over the tree performing an operation over the  
nodes (such as printing their values).  
•
Different traversal orders are possible.  
–
–
Search: checks if a value exists in the tree an
Remove: removes a node from the tree.  
Binary Tree  
•
•
Tree operations:  
–
Recursive implementation  
–
Use of the recursive structure of the tree  
A binary tree is:  
–
An empty tree; or  
–
A root node with two subtrees:  
•
The left subtree (lst);  
root  
•
The right subtree (rst);  
empty  
lst  
rst  
Binary Tree – Create  
•
•
Creates a root node given the information and the two  
subtrees, the one on the left and the one on the right.  
Constructor method of the BTreeNode class:  
public BTreeNode(T t, BTreeNode<T> l, BTreeNode<T> r)  
{
left = l;  
right = r;  
data = t;  
}
Binary Tree – IsEmpty  
•
Indicates whether a given tree is empty or not.  
–
The operation is not part of the generic node class, so a type for the  
data must be defined (example: string).  
public bool IsEmpty(BTreeNode<string> node)  
{
if (node == null)  
return true;  
else  
return false;  
}
Binary Tree – Traverse  
•
Recursively iterates over the tree, visiting all nodes and  
performing an operation over the data (example: printing the  
data).  
–
The operation is not part of the generic node class, so a type for the  
data must be defined (example: string).  
public static void PrintTree(BTreeNode<string> node)  
{
if (!IsEmpty(node))  
{
Debug.Log(node.Data);  
PrintTree(node.Left);  
PrintTree(node.Right);  
}
}
Binary Tree – Creating a Tree  
/
* subtree "d" */  
BTreeNode<string> a1 = new BTreeNode<string>("d", null, null);  
* subtree "b" */  
BTreeNode<string> a2 = new BTreeNode<string>("b", null, a1);  
* subtree "e" */  
BTreeNode<string> a3 = new BTreeNode<string>("e", null, null);  
* subtree "f" */  
BTreeNode<string> a4 = new BTreeNode<string>("f", null, null);  
* subtree "c" */  
BTreeNode<string> a5 = new BTreeNode<string>("c", a3, a4);  
* subtree "a" */  
BTreeNode<string> root = new BTreeNode<string>("a", a2, a5);  
/
/
/
/
/
Binary Tree – Creating a Tree  
BTreeNode<string> root = new BTreeNode<string>("a",  
new BTreeNode<string>("b",  
null,  
new BTreeNode<string>("d", null, null)  
)
,
new BTreeNode<string>("c",  
new BTreeNode<string>("e", null, null),  
new BTreeNode<string>("f", null, null)  
)
);  
Binary Tree – Traverse  
•
It is possible to format the printing to better show the tree  
structure.  
public static void PrintTreeFormated(BTreeNode<string> node,  
int level){  
if (!IsEmpty(node))  
{
PrintTreeFormated(node.Right, level + 1);  
string spaces = "";  
for (int i = 0; i < level; i++)  
spaces += "\t";  
Debug.Log(spaces + node.Data);  
PrintTreeFormated(node.Left, level + 1);  
Does not work  
well on Unity  
console  
}
}
Binary Tree – Search  
•
Checks for the occurrence of a string s in one of the nodes;  
–
Returns a Boolean value indicating whether s exists or not in the tree.  
public static bool SearchTree(BTreeNode<string> node, string s)  
{
if (IsEmpty(node))  
return false;  
else{  
if (node.Data.Equals(s))  
return true;  
else if (SearchTree(node.Left, s))  
return true;  
else if (SearchTree(node.Right, s))  
return true;  
else  
return false;  
}
}
Binary Trees – Traverse Order  
•
•
•
Pre-order:  
–
Access data, traverse lst, traverse rst;  
–
Example: a b d c e f  
In-order:  
–
Traverse lst, acess data, traverse rst;  
–
Example: b d a e c f  
Post-order:  
–
Traverse lst, traverse rst, acess data;  
–
Example: d b e f c a  
Binary Tree – Example  
•
Considering a binary tree to represent arithmetic expressions:  
–
Leaf nodes represent operands;  
–
Internal nodes operators;  
–
Example: (3 + 6) * (4 - 1) + 5  
Binary Tree – Example  
•
Create a function to print the expression that is encoded in a  
binary tree.  
•
For the tree example, the function must print the following  
expression:  
(((3+6)*(4-1))+5)  
Binary Tree – Example  
•
Create the tree:  
BTreeNode<string> node1 = new BTreeNode<string>("3", null, null);  
BTreeNode<string> node2 = new BTreeNode<string>("6", null, null);  
BTreeNode<string> node3 = new BTreeNode<string>("4", null, null);  
BTreeNode<string> node4 = new BTreeNode<string>("1", null, null);  
BTreeNode<string> node5 = new BTreeNode<string>("5", null, null);  
BTreeNode<string> node6 = new BTreeNode<string>("+", node1, node2);  
BTreeNode<string> node7 = new BTreeNode<string>("-", node3, node4);  
BTreeNode<string> node8 = new BTreeNode<string>("*", node6, node7);  
BTreeNode<string> node9 = new BTreeNode<string>("+", node8, node5);  
Binary Tree – Example  
•
Print the expression:  
public static string PrintTreeExp(BTreeNode<string> node){  
string exp = "";  
if (!IsEmpty(node)){  
if ((IsEmpty(node.Left)) && (IsEmpty(node.Right)))  
exp = node.Data;  
else{  
exp = "(";  
exp += PrintTreeExp(node.Left);  
exp += node.Data;  
exp += PrintTreeExp(node.Right);  
exp += ")";  
}
}
return exp;  
}
Binary Tree – Example  
•
Create a function to evaluate the expression encoded in a  
binary tree.  
–
For the example, the result of the expression is: 32  
Binary Tree – Example  
•
Evaluate the expression:  
public static float EvaluateTreeExp(BTreeNode<string> node)  
{
if ((IsEmpty(node.Left)) && (IsEmpty(node.Right)))  
return float.Parse(node.Data);  
else{  
if (node.Data.Equals("+"))  
return EvaluateTreeExp(node.Left) + EvaluateTreeExp(node.Right);  
else if (node.Data.Equals("-"))  
return EvaluateTreeExp(node.Left) - EvaluateTreeExp(node.Right);  
else if (node.Data.Equals("*"))  
return EvaluateTreeExp(node.Left) * EvaluateTreeExp(node.Right);  
else  
return EvaluateTreeExp(node.Left) / EvaluateTreeExp(node.Right);  
}
}
Assignment 1 – Tree  
1
) Create a class to represent a general tree data structure.  
–
Every node of the tree can have N children.  
root  
subtrees  
–
–
The children must be stored in a linked list:  
public class TreeNode<T> : IComparable  
{
private T data;  
private LinkedList<TreeNode<T>> children;  
...  
The following operations must be implemented:  
•
Create, IsEmpty, Print, and Search.  
Binary Search Tree (BST)  
•
•
The value associated with the root is  
always greater than the value associated  
with any node in the left subtree (lst);  
The value associated with the root is  
always less than or equal than the value  
associated with any node in the right  
subtree (rst);  
•
When the tree is traversed in symmetrical  
order (lst - root - rst), the values are  
found in ascending order;  
Search in a Binary Search Tree  
•
Compare the given value with the value  
associated with the root:  
–
–
–
If it is equal, the value was found;  
If it is smaller, the search continues on the lst;  
If it is larger, the search continues on rst;  
Search in a Binary Search Tree  
•
•
In balanced trees the inner nodes have all, or almost all, 2  
children;  
Any node can be reached from the root in O(log n) steps;  
Search in a Binary Search Tree  
•
•
In degenerated trees, all nodes have only 1 child, except for the  
(single) leaf;  
Any node can be reached from the root in O(n) steps;  
Completly  
Unbalanced  
Degenerated)  
Completly  
Balanced  
Balanced  
Unbalanced  
(
Binary Search Tree – Traverse  
•
It is possible to print the values in ascending order, traversing  
the nodes in symmetrical order:  
public static void PrintBST(BTreeNode<int> node)  
{
if (!IsEmpty(node))  
{
PrintBST(node.Left);  
Debug.Log(node.Data);  
PrintBST(node.Right);  
}
}
Binary Search Tree – Search  
•
Explores the ordering property of the tree;  
–
The computational performance is proportional to the height of the  
tree;  
public static BTreeNode<int> SearchBST(BTreeNode<int> node, int v)  
{
if (node == null)  
return null;  
else if (node.Data > v)  
return SearchBST(node.Left, v);  
else if (node.Data < v)  
return SearchBST(node.Right, v);  
else  
return node;  
}
Binary Search Tree – Insert  
•
•
Input: a value v to be inserted;  
Output: a possible new root node for the tree/subtree;  
•
To insert v on the correct position:  
–
If the subtree is empty:  
• Create a tree whose root contains v;  
–
If the subtree is not empty:  
•
Compare v with the value in the root;  
•
Try to insert v in lst or rst, depending on the result of the comparison;  
Binary Search Tree – Insert  
public static BTreeNode<int> InsertBST(BTreeNode<int> node, int v)  
{
if (node == null)  
node = new BTreeNode<int>(v, null, null);  
else if (node.Data > v)  
node.Left = InsertBST(node.Left, v);  
else  
node.Right = InsertBST(node.Right, v);  
return node;  
}
Binary Search Tree – Insert  
create  
insert 6  
insert 4  
insert 8  
insert 2  
insert 5  
insert 1  
insert 3  
insert 7  
insert 9  
Binary Search Tree – Insert  
create  
insert 6  
insert 4  
insert 8  
insert 2  
insert 5  
insert 1  
insert 3  
insert 7  
insert 9  
insert 6  
Binary Search Tree – Insert  
create  
insert 6  
insert 4  
insert 8  
insert 2  
insert 5  
insert 1  
insert 3  
insert 7  
insert 9  
insert 6  
Binary Search Tree – Insert  
public static BTreeNode<int> InsertBST(BTreeNode<int> node, int v)  
{
if (node == null)  
node = new BTreeNode<int>(v, null, null);  
else if (node.Data > v)  
node.Left = InsertBST(node.Left, v);  
else if(node.Data < v)  
node.Right = InsertBST(node.Right, v);  
return node;  
}
Binary Search Tree – Remove  
•
•
Input: a value v to be removed;  
Output: a possible new root node for the tree/subtree;  
•
To remove v:  
–
If the subtree is empty:  
•
nothing has to be done;  
–
If the subtree is not empty:  
•
•
•
•
compare the value stored at the root node with v:  
if it is greater than v, remove the element from the left subtree;  
if it is less than v, remove the element from the right subtree;  
if it is equal to v, remove the root from the tree;  
Binary Search Tree – Remove  
•
To remove the root from the tree, there are 3 cases:  
–
–
–
Case 1: the node to be removed is a leaf node;  
Case 2: the node to be removed has a single child;  
Case 3: the node to be removed has two children;  
BST – Remove Leaf Node  
•
Case 1: the node to be removed is a leaf node:  
–
Remove the node by returning the updated node, which will be null  
remove 3  
remove  
node 3  
BST – Remove Single Child Node  
•
Case 2: the node to be removed has a single child :  
–
The child node becomes the child of the parent node;  
remove 4  
remove  
node 4  
BST – Remove Two Children Node  
•
Case 3: the node to be removed r has two children  
–
find the node N that precedes r in the ordering (the rightmost element  
of the left subtree)  
–
–
swap the value of r with the value of N  
remove N from the left subtree (which now contains the value to be  
removed)  
•
removing the rightmost node N is simple, as N is a leaf node or N is a node with a  
single child (in this case, the right child never exists)  
remove 6  
swap 6  
and 4  
remove  
node 6  
public static BTreeNode<int> RemoveBST(BTreeNode<int> node, int v){  
if (node == null)  
return null;  
else if (node.Data > v)  
node.Left = RemoveBST(node.Left, v);  
else if (node.Data < v)  
node.Right = RemoveBST(node.Right, v);  
else{ /* found the node to remove */  
if (node.Left == null && node.Right == null) /* case 1: leaf node */  
node = null;  
else if (node.Left == null) /* case 2: single child to the left */  
node = node.Right;  
else if (node.Right == null) /* case 2: single child to the right */  
node = node.Left;  
else{  
/* case 3: node has two children */  
BTreeNode<int> f = node.Left;  
while (f.Left != null) /* search for a single child or leaf node */  
f = f.Right;  
node.Data = f.Data; /* swap the values */  
f.Data = v;  
node.Left = RemoveBST(node.Left, v);  
}
}
return node;  
}
Applications in Game Programming  
•
Branching narrative structures: each node represents a  
narrative event or a sequence of events.  
•
•
•
Dialog trees: branching nodes represent dialog choices that  
lead to different dialogs.  
Pathfinding: pathfinding algorithms use tree structures to  
store the search data.  
Decision trees, behavior trees, etc.  
Assignment 2 – Tree  
1
) Implement a tree-based dialog system to represent the  
following
–
–
Every node of the tree must store the dialog text and the interaction option  
that led to the node.  
A way to see and interact with the dialog tree must be implemented.  
•
No graphical interface is required. The dialogs can be displayed in the console and the player  
interaction can be done by pressing keys (e.g.: 1 – selects the first child option; 2 – selects  
the second child option).  
Further Reading  
•
•
Penton, R. (2002). Data Structures for Game Programmers.  
Muska & Lipman/Premier-Trade. ISBN: 978-1931841948  
–
–
–
Chapter 11: Trees  
Chapter 12: Binary Trees  
Chapter 13: Binary Search Trees  
Sherrod, A. (2007). Data Structures and Algorithms for  
Game Developers. Charles River Media. ISBN: 978-  
1584504955  
–
Chapter 9: Trees