Trees and Traversal

Material adapted – courtesy of Prof. Dave Matuszek at UPENN

Definition of a tree

 A tree is a node with a value and zero or more children

 Depending on the needs of the program, the children may or may not be ordered

 A tree has a root, internal nodes, and leaves A  Each node contains an element and has branches B C D E leading to other nodes (its children) F G H I J K  Each node (other than the root) has a parent L M N  Each node has a depth (distance from the root)

2

1 More definitions

 An empty tree has no nodes  The descendents of a node are its children and the descendents of its children  The ancestors of a node are its parent (if any) and the ancestors of its parent  The subtree rooted at a node consists of the given node and all its descendents  An ordered tree is one in which the order of the children is important; an unordered tree is one in which the children of a node can be thought of as a set  The branching factor of a node is the number of children it has  The branching factor of a tree is the average branching factor of its nodes

3

File systems

 File systems are almost always implemented as a tree structure

 The nodes in the tree are of (at least) two types: folders (or directories), and plain files

 A folder typically has children—subfolders and plain files

 A plain file is typically a leaf

4

2 Family trees

 It turns out that a tree is not a good way to represent a family tree

 Every child has two parents, a mother and a father

 Parents frequently remarry  An “upside down” almost works

 Since it is a biological fact (so far) that every child has exactly two parents, we can use left child = father and right child = mother

 The terminology gets a bit confusing

 If you could go back far enough, it becomes a mathematical certainty that the mother and father have some ancestors in common

5

Part of a genealogy

Chester Elaine Eugene Pauline

David Paula Winfred Carol

Steven Danielle

Isaac

6

3 Game trees

 Trees are used heavily in implementing games, particularly board games  A node represents a position on the board  The children of a node represent all the possible moves from that position

 More precisely, the branches from a node represent the possible moves; the children represent the new positions  Planning ahead (in a game) means choosing a path through the tree  However—

 You can’t have a cycle in a tree

 If you can return to a previous position in a game, you have a cycle

 Graphs can have cycles

7

Tree searches

 A tree search starts at the root A and explores nodes from there, looking for a goal node (a node that satisfies certain B C conditions, depending on the problem) D E F G  For some problems, any goal node is acceptable (N or J); H I J K for other problems, you want a minimum-depth goal node, that is, a goal node nearest the L M N O P Q root (only J) Goal nodes

8

4 Depth-first searching

 A depth-first search (DFS) A explores a path all the way to a leaf before and exploring another path B C  For example, after searching A, then B, then D, the search D E F G backtracks and another path from B

H I J K  Node are explored in the order A B D E H L M N I O P C F G J K Q

L M N O P Q  N will be found before J

9

How to do depth-first searching

 Put the root node on a stack; while (stack is not empty) { remove a node from the stack; if (node is a goal node) return success; put all children of node onto the stack; } return failure;

 At each step, the stack contains some nodes from each of a number of levels

 The size of stack that is required depends on the branching factor b

 While searching level n, the stack contains approximately b*n nodes

10

5 Recursive depth-first search

 Recursion is always implemented with a stack.  Anything you can do with recursion, you can do with stacks, and vice-versa

 search(node): print node and if node is a goal, return success; for each child c of node { print c and if search(c) is successful, return success; } return failure;

11

Recursive depth-first search

 search(node): print node and if node is a goal, return success; for each child c of node { print c and if search(c) is successful, return success; } return failure;

 The (implicit) stack contains only the nodes on a path from the root to a goal

 When a solution is found, the path is on the (implicit) stack, and can be extracted as the recursion “unwinds”

 You can do this by (for example) substituting pushing values onto a stack for the above print statements

12

6 Breadth-first searching

 A breadth-first search (BFS) A explores nodes nearest the root before exploring nodes further away B C  For example, after searching A, then B, then C, the search D E F G proceeds with D, E, F, G

 Node are explored in the order H I J K A B C D E F G H I J K L M N O P Q  J will be found before N L M N O P Q

13

How to do breadth-first searching

 Put the root node on a queue; while (queue is not empty) { remove a node from the queue; if (node is a goal node) return success; put all children of node onto the queue; } return failure;

14

7 Comparison of algorithms

 Depth-first searching:

 Put the root node on a stack; while (stack is not empty) { remove a node from the stack; if (node is a goal node) return success; put all children of node onto the stack; } return failure;  Breadth-first searching:

 Put the root node on a queue; while (queue is not empty) { remove a node from the queue; if (node is a goal node) return success; put all children of node onto the queue; } return failure;

15

How to do breadth-first searching

 Put the root node on a queue; while (queue is not empty) { remove a node from the queue; if (node is a goal node) return success; put all children of node onto the queue; } return failure;  Just before starting to explore level n, the queue holds all the nodes at level n-1  In a typical tree, the number of nodes at each level increases exponentially with the depth  Memory requirements may be infeasible  When this method succeeds, it doesn’t give the path  There is no “recursive” breadth-first search equivalent to recursive depth-first search

16

8 Depth- vs. breadth-first searching

 When a breadth-first search succeeds, it finds a minimum-depth (nearest the root) goal node  When a depth-first search succeeds, the found goal node is not necessarily minimum depth  For a large tree, breadth-first search memory requirements may be excessive  For a large tree, a depth-first search may take a very long time to find even a very nearby goal node  There is a way to combine the two, but it is beyond the scope of this class. Channel your inner Googler to look up Depth-limited searching and iterative deepening.

17

Thank you!

18

9