Trees. A tree consists of a set of nodes and a set of edges connecting the nodes, where there is only one path between any two nodes. A tree is thus a graph with no cycles and all vertices connected.
Traversals. Iteration over a tree is known as a tree traversal. There are multiple ways of traversing trees given by when we “visit” each node.
Level-Order Traversal. A level-order traversal visits every item at level 0, then level 1, then level 2, and so forth.
Depth-First Tree Traversals. We have three depth-first traversals: pre-order, in-order, and post-order. In a pre-order traversal, we visit the current node then traverse its children. In an in-order traversal, we traverse the left child, visit the current node, then traverse the right child. In a post-order traversal, we traverse both children before visiting the current node. These are very natural to implement recursively. Pre-order and post-order generalize naturally to trees with arbtirary numbers of children. In-order only makes sense for binary trees.
Graphs. A graph consists of a set of nodes and a set of edges connecting the nodes. However, unlike our tree definition, we can have more than one path between nodes. Note that all trees are graphs but not all graphs are trees. In this course, we can assume all graphs are simple graphs containing no self-loops or parallel edges.
Depth-First Search. DFS for graphs is similar to depth-first traversals for trees. However, since there can exist cycles within our graph, we need to check that each vertex should be visited at most once. This can be accomplished by marking nodes as visited and only visiting a node if it had not been marked as visited already.