A path in a tree is a sequence of (zero or more) connected nodes; for example, here are 3 of the paths in the tree shown above:
The length of a path is the number of nodes in the path, e.g.:
The height of a tree is the length of the longest path from the root to a leaf; for the above example, the height is 4 (because the longest path from the root to a leaf is
The depth of a node is the length of the path from the root to that node; for the above example:
Node A is called the parent, and node B is called the child.
A subtree of a given node includes one of its children and all of that child's descendants. The descendants of a node n are all nodes reachable from n (n's children, its children's children, etc.). In the original example, node A has three subtrees:
The two trees are different because the children of node B are different:
in the first tree, B's left child is D and its right child is E; in the
second tree, B's left child is E and its right child is D. Also note that
lines are used instead of arrows. We sometimes do this because it is clear
that the edge goes from the higher node to the lower node.
class BinaryTreenode { Object data; BinaryTreenode leftChild; BinaryTreenode rightChild; }
class Treenode { Object data; Sequence children; }(Note that the items in the sequence will be of type Treenode.)
As we know, a sequence can be represented using either an array or a linked-list. For example, consider this general tree (a simplified version of the original example):
For the array representation of the Sequence (where the array has an initial size of 4) we would have:
Draw a similar picture of the tree when the Sequence fields are implemented using linked lists.
For trees, there are many different orders in which we might visit the nodes. There are three common traversal orders for general trees, and one more for binary trees: preorder, postorder, level order, and in-order, all described below. We will use the following tree to illustrate each traversal:
Preorder
A preorder traversal can be defined (recursively) as follows:
Postorder
A postorder traversal is similar to a preorder traversal, except that the root of each subtree is visited last rather than first:
Level order
The idea of a level-order traversal is to visit the root, then visit all nodes "1 level away" (depth 2) from the root (left to right), then all nodes "2 levels away" (depth 3) from the root, etc. For the example tree, the goal is to visit the nodes in the following order:
A level-order traversal requires using a queue (rather than a recursive algorithm, which implicitly uses a stack). Here's how to print the data in a tree T in level order, using a queue Q:
Q.enqueue(root) while (!Q.isEmpty()) { n = Q.dequeue(); System.out.print(n.data); s = n.children; s.start(); try { while (s.isCurrent() { Q.enqueue(s.getCurrent()); s.advance(); } } catch (NoCurrentException e) {} // can't happen }
Draw pictures of Q as it would be at the start of the outer while loop in the code given above for the example tree given above.
An in-order traversal involves visiting the root "in between" visiting its left and right subtrees. Therefore, an in-order traversal only makes sense for binary trees. The (recursive) definition is:
The primary difference between the preorder, postorder and in-order traversals is where the node is visited in relation to the recursive calls; i.e., before, after or in-between.
What is printed when the following tree is visited using (a) a preorder traversal, (b) a postorder traversal, (c) a level-order traversal, and (d) an in-order traversal?
solution