A tree is a type of dynamic data structure that consists of nodes linked to a single parent node (except for the root node) and which can be linked to multiple children nodes. Each node contains "three" parameters, the data, some data structure storing the address of it's children nodes, and a address to it's parent node.
The tree data structure can be thought of as an implementation of a finite tree. Tree's can alternatively be thought of as a subset of graphs which have no cycles. Because tree's have no cycles, recursion is a useful technique for traversing them.
Tree's are a type of graph and thus the same terminology also applies, each connection between a parent and a child is an edge.
Tree traversal refers to the process by which you access nodes in the tree, each defines a specific order, and each no is only visited once.
Depth first traversal is a method of traversing trees which explores as far along a given branch as possible before exploring the next branch.
There are 2 general types of depth-first traversal, each of which determines the order in which the root is visited compared to the subtree are visited.
In preorder traversal, the node is processed before its subtrees. This traversal is useful for creating a copy of the tree or generating a prefix notation of an expression tree.
class Node:
def __init__(self, value, children=None):
self.value = value
self.children = children or []
def preorder_traverse(root, visit):
if root is None:
return
visit(root.value)
for child in root.children:
preorder_traverse(child, visit)
In postorder traversal, the node is processed after its subtrees. This traversal is useful for tasks such as deleting the tree or generating a postfix notation of an expression tree. It works for general trees as well.
class Node:
def __init__(self, value, children=None):
self.value = value
self.children = children or []
def postorder_traverse(root, visit):
if root is None:
return
for child in root.children:
postorder_traverse(child, visit)
visit(root.value)
Breadth first traversal is a method of traversing trees which explores all the nodes at a give level before descending to the next.
The standard implementation uses a queue where elements are pulled from the front of the queue to be processed and then their children are pushed to the end of the queue.
from collections import deque
class Node:
def __init__(self, value, children=None):
self.value = value
self.children = children or []
def breadth_first_traversal(root, visit):
if root is None:
return
queue = deque([root])
while queue:
current_node = queue.popleft()
visit(current_node.value)
if current_node.left:
queue.append(current_node.left)
if current_node.right:
queue.append(current_node.right)