TREES
In trees, there is a branching relationship between nodes. A tree is a finite set T of one or more
nodes such that:
(a) there is one specially designated node called the root of the tree, root(T );
(b) the remaining nodes are partitioned into m ≥ 0 disjoint sets T [1], T [2], T [3], . . . , T [m], and
each of these sets in turn is a tree.
The trees T [1], T [2], . . . , T [m] are called the subtrees of the root.
Examples of tree-like structures include family trees, any hierarchical classification (e.g., Dewey
decimal coding, Unix or Windows file directory structure), algebraic formulae and parse trees.
The degree of a node is the number of subtrees of that node.
A terminal node, or leaf, is a node of degree zero.
A branch node is a node which is not a terminal node.
The level of a node with respect to tree T is defined by saying that the root has level 1, the roots of
the subtrees of T have level 2, the roots of the subtrees of the subtrees of T have level 3 and so on.
(Some people define the level of the root as 0, and then the levels of the other nodes are decreased
by one correspondingly.) We will sometimes refer to a “level n tree”, meaning a tree whose root is
at level n with respect to another tree.
An ordered tree is one in which the order (1st, 2nd, etc.) of subtrees at each level is defined; an
oriented tree is one in which the subtrees may exist in any order. Unless the word “oriented” is
used, references to “tree” will denote an ordered tree.
A root R is the parent of the roots of its subtrees, which are known as children of R. The set
of children of a parent are siblings. Definitions of ancestor and descendant follow from these
definitions.
A forest is an (ordered) set of disjoint trees (or “a tree without its root”).
Notation: If F is an ordered forest of trees, let F [n] denote the nth tree and F [n, p] the pth
subtree of the nth tree etc.; for example, G[2, 5, 3] denotes the 3rd subtree of the 5th subtree of the
2nd tree of forest G, and root(G[2, 5, 3]) is its root. Notice the obvious relationship between this
notation and Dewey classification.
Notice also that an array of any number of dimensions may be regarded as a tree structure. For
example, a 3 × 4 matrix may be regarded as a forest of three trees (representing the rows), each
of which has four level 2 trees (in this case the nodes) representing the elements. This structure
reflects a particular ordering of the dimensions of the array; in this example, columns do not appear
as trees.
14
BINARY TREES
A binary tree is a finite set of nodes which either is empty or consists of a root and an ordered pair
of disjoint binary trees, known as the left and right subtrees of the root (i.e. each node has 0, 1
or 2 children). Notice that binary trees are not simply trees in which the number of children per
node is limited to a maximum of two; binary trees are a distinct concept from trees. In particular:
(a) a binary tree may be empty;
(b) the following represent the same tree but different binary trees.
A binary tree is represented in store by having a pointer variable (say T) pointing to the
representation of the root node; T = nil represents an empty tree. Each node is represented by
three fields:
LLINK points to the left child (or is nil); RLINK points to the right child (or is nil). INFO may be
some information at the node or a pointer to that information.
Traversing a binary tree
Traversing a binary tree means visiting (i.e., performing some operation at) each node of the tree.
The three main methods of traversal are pre-order, in-order and post-order, defined recursively as
follows:
If the tree is empty, do nothing; otherwise:
Pre-order
Visit root
Do left subtree
Do right subtree
In-order
Do left subtree
Visit root
Do right subtree
For example, for the following tree:
15
Post-order
Do left subtree
Do right subtree
Visit root
the order of visiting the nodes is:
Pre-order
In-order
Post-order
:
:
:
124536
425136
452631
Using recursion, the traversal algorithms are simple, e.g.:
void pre_traverse(Pointer P)
{
if (P 6= nil)
{
visit(P);
pre_traverse(P↑LLINK);
pre_traverse(P↑RLINK);
}
}
We assume that the type Pointer has been defined by the type definition:
typedef Node* Pointer;
The recursive algorithms disguise the facts that the program may use a considerable amount of
store for a stack, and that both the value of P and a return link (address) must be stacked on each
entry to the procedure and unstacked on each exit. We can use the same technique but dispense
with return links; this yields the following (less natural) iterative algorithm, which is essentially a
“mechanical” translation of the recursive algorithm above. (We assume the existence of a procedure
CLEAR(A) which sets stack A to be empty and a function EMPTY(A) which tests if stack A is empty.)
void pre_traverse(Pointer P)
{
Pointer_stack A;
CLEAR(A);
while (true)
{
if (P 6= nil)
{
VISIT(P);
STACK(A,P);
P ← P↑LLINK;
}
else
{
if (EMPTY(A))
return;
else
{
P ← UNSTACK(A);
P ← P↑RLINK;
}
}
}
}
16
© Copyright 2026 Paperzz