READING-NOTE

View on GitHub

Trees

Common Terminology

Sample Tree

Traversals

Depth First

Breadth-First

Depth First

Pre-order: root » left » right

In-order: left » root » right

Post-order: left » right » root

Given the sample tree above, our traversals would result in different paths:

Pre-order: A, B, D, E, C, F

In-order: D, B, E, A, F, C

Post-order: D, E, B, F, C, A

The most common way to traverse through a tree is to use recursion. With these traversals, we rely on the call stack to navigate back up the tree when we have reached the end of a sub-path.

Pre-order

Let’s break down the pre-order traversal. Here is the pseudocode for this traversal method:

ALGORITHM preOrder(root)

  OUTPUT <-- root.value

  if root.left is not NULL
      preOrder(root.left)

  if root.right is not NULL
      preOrder(root.right)

It’s important to note a few things that are about to happen:

Breadth First

Our output using breadth first traversal is now:

Output: A, B, C, D, E, F

Given our starting tree shown above, let’s start by putting the root into the queue:

Now that we have one node in our queue, we can dequeue it and use that node in our code.

From our dequeued node A, we can enqueue the left and right child (in that order).

Pseudocode Here is the pseudocode, utilizing a built-in queue to implement a breadth first traversal.

ALGORITHM breadthFirst(root)
#// INPUT  <-- root node
#// OUTPUT <-- front node of queue to console

  #Queue breadth <-- new Queue()
  #breadth.enqueue(root)

  while breadth.peek()
    node front = breadth.dequeue()
    OUTPUT <-- front.value

    if front.left is not NULL
      breadth.enqueue(front.left)

    if front.right is not NULL
      breadth.enqueue(front.right)

Binary Tree Vs K-ary Trees

K-ary Trees

Breadth First Traversal

If we traversed this tree Breadth First we should see the output:

Output: A, B, C, D, E, F, G, H

Much like before, as long as we have a node in our queue we can dequeue:

Pseudocode

This process is very similar to our binary tree traversal, but now we check a list of children instead of a left and right child properties. It should look something like this:

#ALGORITHM breadthFirst(root)
#// INPUT  <-- root node
#// OUTPUT <-- front node of queue to console

  Queue breadth <-- new Queue()
  breadth.enqueue(root)

  while breadth.peek()
    node front = breadth.dequeue()
    OUTPUT <-- front.value

    for child in front.children
        breadth.enqueue(child)

Big O

Binary Search Trees

Here is how we would change our Binary Tree example into a Binary Search Tree:

Searching a BST

Searching a BST can be done quickly, because all you do is compare the node you are searching for against the root of the tree or sub-tree. If the value is smaller, you only traverse the left side. If the value is larger, you only traverse the right side.

Let’s say we are searching 15. We start by comparing the value 15 to the value of the root, 23.

15 < 23, so we traverse the left side of the tree. We then treat 8 as our new “root” to compare against.

15 > 8, so we traverse the right side. 16 is our new root.

15 < 16, so we traverse the left side. And aha! 15 is our new root and also a match with what we were searching for.

Big O