Tree traversal algorithm

Posted by pbjpb on Mon, 17 Jan 2022 23:52:16 +0100

1, Several traversal algorithms of tree

1. Preorder traversal

First access the root of T, and then recursively access the root of the subtree. If the tree is ordered, traverse the subtree according to the child's order. The pseudo code for traversing the root of the subtree at position p is:

Algorthm preorder(T, p):
  perform the visit action for positon p
  for each child c in T.children(p) do
    preorder(T, c)

2. Post order traversal

It can be regarded as the opposite preorder traversal, first traversing the subtree, and then visiting the root

Algorithm postorder(T, p):
  for each child c in T.children(p) do
    postorder(T, c)
  perform the visit action for position p

Run time is O(n)

3. Breadth first traversal

Access the position of depth d before accessing the position of depth d+1. Breadth first traversal is widely used in game software.

Algorithm breadthfirst(T):
  Intialize queue Q to contain T.root()
  while Q not empty do:
    p = Q.dequeue() # p is the oldest entry in the queue
    performm the visit action for position p  
    for each child c in T.children(p) do
      Q.enqueue(c)  # add p's children to the end of the queue for later visits

4. Middle order traversal

Access a location by recursively traversing the left and right subtree areas. For a position p, p is accessed in middle order after its left subtree and before its right subtree

Algorithm inorder(p):
  if p has a left child lc then
    inorder(lc)
  perform the visit action for position p
  if p has a right child rc then
    inorder(rc)

Application: arithmetic expression} binary search tree

Binary search tree

Middle order traversal stores the elements of an ordered sequence in a binary tree, which is called a binary search tree. Let s be a set whose unique elements have an order relationship. For example, s may be a set of integers. The binary search tree of S is t. for each position p of T, there are:

  • Position p stores an element of S, denoted e(p)
  • The elements (if any) stored in the left subtree of p are less than e(p)
  • The element (if any) stored in the right subtree of p is greater than e(p)

2, Traversal of tree with Python

Tree T should support the following methods:

  • T.positions(): generates an iterator for all positions in the tree T #
  • iter(T): generates an iterator from all elements of tree t

All elements of the tree can easily produce an iterator, provided that a hypothetical iterator at all positions is practiced. The iter(T) syntax can be given through the concrete implementation of iter, which abstracts the special method of the basic tree class.

def __iter__(self):
  """ Generate an iteration of the tree's elements."""
  for p in self.positions():  # use same order as positions()
    yield  p.element()        # but yield each element

 1. Preorder traversal

A common method is given by calling T.preorder() of tree T, which generates a preorder iterator about all positions of the tree.

Using the above preorder traversal algorithm, the specific position of the tree must be parameterized as the root of the subtree. In this case, the standard solution is to define the non-public application method with the required recursive parameterization, and then the public method preorder calls the non-public method at the root of the tree.

def preorder(self):
  """ Generate a preorder iteration of positions in the tree."""
  if not self.is_empty():
    for p in self._subtree_preorder(self.root()):
      yield p

def _subtree_preorder(self, p):
  """ Generate a preorder iteration of positions in subtree rooted at p."""
  yield p                                    # visit p before its subtree
  for c in self.childern(p)
    for other in self._subtree_preorder(c):
      yield other                            # yielding each to caller

The official tree ADT requires that all trees support the positions method. Here, the preorder traversal is taken as the default iteration order. A loop that returns the entire iteration as an object rather than the return value of a call traversed in sequence.

def positions(self):
  """ Generate an iteration of the tree's positions."""
  return self.preoreder()

2. Post order traversal

def postorder(self):
  """ Generate a postorder iteration of positions in the tree."""
  if not self.is_empty():
    for p in self._subtree_postorder(self.root()):
      yield p

def _subtree_postorder(self, p):
  """ Generate a postorder iteration of positions in subtree at p."""
  for c in self.children(p):
    for other in self._subtree_postorder(c):
      yield other                             # yielding each to caller
  yield p                                     # visit p after its subtrees

3. Breadth first traversal

The breadth first traversal algorithm is not recursive. It uses the location queue to manage the recursive program, which is implemented here using the LinkedQueue class

def breadthfirst(self):
  """ Generate a breadth-first iteration of the positions of the tree."""
  if not self.is_empty():
    fringe = LinkedQueue()
    fringe.enqueue(self.root())
    while not fringe.is_empty():
      p = fringe.dequeue()
      yield p
      for c in self.children(p):
        fringe.enqueue()

4. Middle order traversal

The preorder, postorder and breadth first traversal algorithms can be applied to all trees, so all their implementations are included in the abstract base class of the Tree. These methods can be inherited by abstract binary Tree classes, concrete chain binary Tree classes and other derived classes.

The middle order traversal algorithm explicitly depends on the concept of left and right child nodes and is only applicable to binary trees, so it is implemented in the BinaryTree class.

def inorder(self):
  """ Generate an iterations of positions in the tree."""
  if not self.is_empty():
    for p in self._subtree_inorder(self.root()):
      yield p

def _subtree_inorder(self, p):
  """ Generate an inerations of positions in subtree rooted at p."""
  if self.left(p) is not None:
    for other in self._subtree_inorder(self.left(p)):
      yield other
  yield p
  if self.right(p) is not None:
    for othe in self._subtree_inorder(self.right(p)):
      yield other

Topics: Python data structure