Trees: basic definitions and terminology. Contrary to arrays, stacks, queues and sequences all of which are one dimensional data structures, trees are twodimensional data structures with hierarchical relationship between data items.
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
Contrary to arrays, stacks, queues and sequences all of which are one
dimensional data structures, trees are twodimensional data structures with
hierarchical relationship between data items.
Definition 1 A tree is a nonempty collection of vertices (nodes) and edges that satisfy certain requirements.
Definition 2 A path in a tree is a list of distinct vertices in which successive vertices are connected by edges in the tree.
One node in the tree is designated as the root. Each tree has exactly one
path between the root and each of the other nodes. If there is more than one
path between the root and some node, or no path at all, we have a graph.
Definition 3 A set of trees is called a forest.
Definition 4 (Recursive definition) A tree is either a single node or a root node connected to a forest.
root
siblings
subtree
internal nodes
external nodes, or leaves
Definition 5 An ordered tree is a tree in which the order of children is specified.
Definition 6 A level (depth) of a node in the number of nodes on the path from that node to the root.
Definition 7 The height (maximum distance) of a tree is the maximum level among all of the nodes in the tree.
Definition 8 The path length of a tree is the sum of the levels of all the nodes in the tree.
Definition 9 A tree where each node has a specific number of children appearing in a specific order is call a multiway tree. The simplest type of a multiway tree is the binary tree. Each node in a binary tree has exactly two children one of which is designated as a left child, and the other is designated as a right child.
Definition 10 (Recursive definition) A binary tree is either an external node, or an internal node and two binary trees.
root
left child right child
one or both children
might be external nodes
special external nodes with
no name and no data associated
with them
1. Binary tree for representing arithmetic expressions. The underlying hierarchical relationship is that of an arithmetic operator and its two operands.
Arithmetic expression in an infix form: (A  B) + C * (E / F)
+
 *
A B C /
E F
Note that a postorder traversal of this tree (i.e. visiting the left subtree first, right
subtree next, and finally the root) returns the postfix form of the arithmetic
expression, while the preorder traversal (root is visited first, then the left subtree,
then the right subtree) returns the prefix form of the arithmetic expression.
2. Binary tree with a heap property. The underlying hierarchical relationship suggests that the datum in each node is greater than or equal to the data in its left and right subtrees.
87
84 63
68 79 12
32 67 6 10
8 9
3. Binary tree with an ordering property. The underlying hierarchical relationship suggests that the datum in each node is greater than the data in its left subtree, and less than or equal to the data in its right subtrees.
87
84 103
68 86 90 109
32 74 88 97
70 80
4. Decision trees. The underlying hierarchical relationship depends on the nature of the domain represented by the binary tree. For example, consider a domain that consists of the following statements (from J.Ignizio “Intro to ES”):
The following decision tree can be generated from these rules:
Engine type
Jet Propeller
Wing Position C130
Low High
B747 Bulges
None Aft Wing
C5A C141
1. The number of external nodes is 1 more than the number of internal nodes. It is easy to see this if we start removing external nodes with their internal parent, one pair at a time (assume that a method removeAboveExternal(n) does this). At the end of this process, only the root with its two external children will remain.
2. The number of external nodes is at least h + 1, where h is the height of the tree, and at most 2h. The later holds for a full binary tree, which is a tree where internal nodes completely fill every level.
3. The number of internal nodes is at least h and at most 2h 1.
4. The total number of nodes in a binary tree is at least 2*h + 1 and at most 2h+1  1.
5. The height, h, of a binary tree with n nodes is at least log n+1 and at most n.
6. A binary tree with n nodes has exactly n  1 edges.
Here is an example of a full binary tree:
1
2 3
4 5 6 7
8 9 10 11 12 13 14 15
A complete binary tree is a full binary tree where the internal nodes on the
bottom level all appear to the left of the external nodes on that level. Here is
an example of a complete binary tree:
1
2 3
4 5 6
The following property holds for a complete binary tree.
Let i be a number assigned to a node in a complete binary tree. Then:
1. If i = 1, then this node is the root of the tree. If i > 1, then the parent of this node is assigned the number (i / 2).
2. If 2*i > n, then the corresponding node has no left child. Otherwise, the left child of that node is assigned the number 2*i.
3. If 2*i + 1 > n, then the corresponding node has no right child. Otherwise, the right child of that node is assigned the number 2*i + 1.
This property suggests a trivial arraybased representation of a complete binary
tree, where i is the index of the node in the array. We will see that a slight
modification in this representation allows us to represent any binary tree in a
linear fashion.
We cannot provide a complete specification of the Binary Tree ADT, as we did
with other ADT’s so far, because the hierarchical relationship in the binary tree
cannot be uniquely defined. We define here only a set of basic operations on
binary trees, and more specific binary tree ADT’s will be introduced as the
need arrives.
Operations (methods) on binary trees:
empty () Returns true if the binary tree is empty
getRoot () Returns the root node of the tree
leftChild (node) Returns the left child of node.
rightChild (node) Returns the right child of node.
expandExternal(node) Makes node internal by creating its left and right children
removeAboveExternal(node) Removes an external node together with its parent
insert (node) Inserts node in the appropriate position in the tree
delete (node) Deletes node
preOrder() Visit the root, then the left subtree, then the right subtree
postOrder () Visit the left subtree, then the right subtree, then the root
inOrder() Visit the left subtree, then the root, then the right subtree
levelOrder () Starting from the root, visit tree nodes level by level
Linear representation of a binary tree utilizes onedimensional array of size
2h+1  1. Consider the following tree:
+ level 0 (d = 0)
* level 1 (d = 1)
A B C / level 2 (d = 2)
E F level 3 (d = 3)
To represent this tree, we need an array of size 23+1  1 = 15
The tree is represented as follows:
1. The root is stored in BinaryTree[1].
2. For node BinaryTree[n], the left child is stored in BinaryTree[2*n], and the right child is stored in BinaryTree[2*n+1]
i: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
BinaryTree[i]: +  * A B C / E F
Advantages of linear representation:
1. Simplicity.
2. Given the location of the child (say, k), the location of the parent is easy to determine (k / 2).
Disadvantages of linear representation:
1. Additions and deletions of nodes are inefficient, because of the data movements in the array.
2. Space is wasted if the binary tree is not complete. That is, the linear representation is useful if the number of missing nodes is small.
Note that linear representation of a binary tree can be implemented by means
of a linked list instead of an array. For example, we can use the Positional
Sequence ADT to implement a binary tree in a linear fashion. This way the
above mentioned disadvantages of the linear representation will be resolved.
+

*
A
B
C
/
E
F
Linked representation uses explicit links to connect the nodes. Example:
1
2 5
3 4 6 7
8 9
Nodes in this tree can be viewed as positions in a sequence (numbered 1
through 9).
class BTNode {
char data;
BTNode leftChild;
BTNode rightChild;
BTNode parent;
int pos;
public BTNode () {
}
public BTNode (char newData) {
data = newData;
}
public BTNode (char newData, BTNode newLeftChild, BTNode newRightChild) {
data = newData;
leftChild = newLeftChild;
rightChild = newRightChild;
}
... methods setData, setLeftChild, setRightChild, getData, getLeftChild, getRightChild,
displayBTNode follow next ...
}
We can use a positional sequence ADT to implement a binary tree. Our
example tree, in this case, we be represented as follows:
position 1 2 3 4 5 6 7 8 9
data +  A B * C / E F
leftChild 2 3 null null 6 null 8 null null
rightChild 5 4 null null 7 null 9 null null
parent null 1 2 2 1 5 5 7 7
class BTLRPS implements PSDLL {
private BTNode header;
private BTNode trailer;
private int size;
int position;
... class methods follow ... }
Preorder traversal
public void preOrder (BTNode localRoot) {
if (localRoot != null) {
localRoot.displayBTNode();
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild); } }
Example Consider a tree with an ordering property, where nodes are inserted in the following order b i n a r y t r e e, i.e.
b
a i
e n
e r
y
t
r
The preorder traversal is: b a i e e n r y t r
Postorder traversal
public void postOrder (BTNode localRoot) {
if (localRoot != null) {
postOrder(localRoot.leftChild);
postOrder(localRoot.rightChild);
localRoot.displayBTNode(); } }
The nodes in the example tree are traversed in postorder as follows:
a e e r t y r n i b
Inorder traversal
public void inOrder (BTNode localRoot) {
if (localRoot != null) {
inOrder(localRoot.leftChild);
localRoot.displayBTNode();
inOrder(localRoot.rightChild); } }
The nodes in the example tree are traversed in inorder as follows:
a b e e i n r r t y
Levelorder traversal
public void levelOrder (BTNode localRoot) {
BTNode[] queue = new BTNode[20];
int front = 0;
int rear = 1;
while (localRoot != null) {
localRoot.displayBTNode();
if (localRoot.leftChild != null) {
rear++;
queue[rear] = localRoot.leftChild; }
if (localRoot.rightChild != null) {
rear++;
queue[rear] = localRoot.rightChild; }
localRoot = queue[front];
front++; } }
The nodes in the example tree are traversed in levelorder as follows:
b a i e n e r y t r
3. Application of an inorder traversal: binary search trees
A binary search tree is a tree with an ordering relationship between data in the
nodes (i.e. all nodes with smaller data are in the left subtree and all nodes with
greater or equal data are in the right subtree). See slide 7 for an example
Inorder traversal of a binary search tree produces an ordered list:
32 68 70 74 80 84 86 87 88 90 97 103 109
Binary search trees allow for a very efficient search (in log N time). The idea
of the binary tree search is the following: to find a node with a given datum
(the target), compare the target to the root; if it is smaller, go to the left subtree;
if it is larger, go to the right subtree; if it is equal, stop.
Insert 9 in the the following tree:
3
2 15
1 11
7 13
Step 1: search for 9 3
2 15
1 11
search stops here 7 13
Step 2: insert 9 at the point where the search terminates unsuccessfully
3
2 15
1 11
7 13 That is, new nodes are always inserted at the leaf level.
9
class BTLRADT {
BTNode root;
public BTLRADT () { }
public BTNode getRoot () {
return root; }
public void insert (char newData) {
BTNode newNode = new BTNode ();
newNode.data = newData;
if (root == null)
root = newNode;
else {
BTNode temp = root;
BTNode parent;
while (true) {
parent = temp;
if (newData < temp.data) { //go left
temp = temp.leftChild;
if (temp == null) {
parent.leftChild = newNode;
return; }
}
else { // go right
temp = temp.rightChild;
if (temp == null) {
parent.rightChild = newNode;
return;
}
}
}
}
}
Consider the tree:
3 7
2 15 Deleting 3 2 15
1 11 1 11
7 13 13
The following cases of deletions are possible:
1. Delete a note with no children, for example 1. This only requires the appropriate link in the parent node to be made null.
2. Delete a node which has only one child, for example 15. In this case, we must set the corresponding child link of the parent’s parent to point to the only child of the node being deleted.
3. Delete a node with two children, for example 3. The delete method is based on the following consideration: inorder traversal of the resulting tree (after delete operation) must yield an ordered list. To ensure this, the following steps are carried out:
Step 1: Replace 3 with the node with the next largest datum, i.e. 7.
Step 2: Make the left link of 11 point to the right child of 7 (which is null here).
Step 3: Copy the links from the node containing 3 to the node containing 7, and make the parent node of 3 point to 7.
Assuming that a general tree is implemented as a positional container, the
following is an incomplete set of methods supported by the data structure:
The depth of a tree node is a number of ancestors of that node, excluding the node itself. That
is, the depth of the root is 0, while the depth of any other node is the depth of its parent plus
one. The method, depth, can be implemented recursively as follows:
public int depth (int position) {
if (isRoot(position))
return 0;
else
return (1 + depth(parent(position))); }
The height of the tree is equal to the maximum depth of external nodes of the tree. The
method height can be implemented as follows:
public int height () {
int h = 0;
Enumeration nodes = positions();
while (nodes.hasMoreElements()) {
int nextNode = nodes.nextElement ();
if (isExternal(nextNode))
h = Math.max(h, depth(nextNode));
}
return h; }
Consider the following genealogical tree
Jim
Bill Katy Mike Tom
Dave Mary Leo Bety Rog
Lary Paul Peny Don
We can represent it in the following binary tree format:
1 Jim
2 Bill 8 Katy 10 Mike 14 Tom
3 Dave 4 Mary 9 Leo 11 Bety 13 Rog
5 Lary 6 Paul 7 Peny 12 Don
In the resulting binary tree, the leftchild pointer (we can call it here the children
pointer) points to the first child of the ordered list of children, while the rightchild
pointer (we can call it here the sibling pointer) points to the next sibling of a node.
We can represent the resulting binary tree as a positional sequence:
position 1 2 3 4 5 6 7 8 9 10 11 12 13 14
data Jim Bill Dave Mery Lary Paul Peny Katy Leo Mike Bety Don Rog Tom
firstChild 2 3 null 5 null null null 9 null 11 12 null null null
sibling null 8 4 null 6 7 null 10 null 14 13 null null null
parent null 1 2 3 4 5 6 2 8 8 10 11 11 10
class TNode {
private String data;
private TNode children, sibling;
int position;
... class methods follow ...
}
Consider our example tree
Jim
Bill Katy Mike Tom
Dave Mary Leo Bety Rog
Lary Paul Peny Don
Preorder traversal is:
Jim Bill Dave Mary Lary Paul Peny Katy Leo Mike Bety
Don Rog Tom
Postorder traversal is:
Dave Lary Paul Peny Mary Bill Leo Katy Don Bety Rog
Mike Tom Jim
Preorder traversal works as follows: 1.) select a node and visit it and its children;
2.) go to the next node at the same level and do the same until all of the tree
nodes are processed.
Algorithm preOrder (TNode)
visit TNode
for each child TNodeChild of TNode do
recursively perform preOrder(TNodeChild)
Or, in JAVA:
public void preOrder (TNode localRoot) {
localRoot.displayTNode();
Enumeration localRootChildren = localRoot.children(localRoot.getPosition());
while (localRootChildren.hasMoreElements()) {
TNode nextNode = localRootChildren.nextElement();
preOrder (nextNode); } }
Note: If a general tree is represented as a binary tree, a preorder traversal of the
general tree and the corresponding binary tree, produces the same result.
In postorder traversal, the tree is processed from left to right, ensuring that no
node is processed until all nodes below it are processed. That is,
Algorithm postOrder (TNode)
for each child TNodeChild of TNode do
recursively perform postOrder(TNodeChild)
visit TNode
Or, in JAVA:
public void postOrder (TNode localRoot) {
Enumeration localRootChildren = localRoot.children(localRoot.getPosition());
while (localRootChildren.hasMoreElements()) {
TNode nextNode = localRootChildren.nextElement();
postOrder (nextNode); }
localRoot.displayTNode(); }
Note: If a general tree is represented as a binary tree, a postorder traversal of the
general tree and the corresponding binary tree, do not generate the same result.
However, the inorder traversal of the corresponding binary tree generates the
same result as the postorder traversal of the general tree.
If node siblings in a general tree form ordered lists, then we can represent the
tree as a ternary tree. In a ternary tree, each node has the following attributes:
Consider the example tree:
Jim
Bill Katy Mike Tom
Dave Mary Leo Bety Rog
Lary Paul Peny Don
Represented as a ternary tree, it looks like as follows:
Jim
Bill Katy Mike Tom
Dave Mary Leo Bety Rog
Lary Paul Peny Don
The idea is the following: for each node do 1.) process the node, and 2.) access
the binary tree representing its children, and process this binary tree inorder.
Algorithm preorderTernary (ternaryNode)
if (ternaryNode is internal node) {
preorder (ternaryNode.leftSibling)
process ternaryNode
inorder (ternaryNode.children)
preorder (ternaryNode.rightSibling)
}