0% found this document useful (0 votes)
12 views

Lesson 06s SDD

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Lesson 06s SDD

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

ITE 2142 – Data Structures & Algorithms Week 06

LESSON 06 – Trees

Introduction

We have studied stack, queues and lists which are special form of sequences. Sequences are
classified as linear data structures. The linear data structure is one each component has a
unique predecessor component and a unique successor component. Trees and graphs in
contrast to sequences are nonlinear data structure, since they contain component which may
have more than one successor and more than one predecessor. During this lesson we learn
about trees and how to implement tree structure in Java.

Learning outcome
After completing this lesson, you would be able to define trees and different types of operations
can be performed over them. Thus you should be able to,
 Define a binary tree
 Describe trees operations
 Compare and contrast different types of trees
 Define heaps

6.1 Introduction to Trees


A tree is a nonlinear data structure of with each component or ‘node’ has only one and only
predecessor node except for the root node which has null but has zero or no successor node.
Every non empty tree contain a distinguish node which has no predecessor which is called
“root node”. Formally tree can be defined as a collection of nodes with values of some type
T either empty or consists of another node with values of type T. A tree can be depicted as
follows.
Level 1

Level 2

Level 3
1
Trees
ITE 2142 – Data Structures & Algorithms Week 06

Note that in the above tree A is the root node.

6.1 Basic Tree Terminology


6.1.1 Degree of a node
The number of sub trees of a node is called it degree. For example the degree of A is three,
the degree of B is one and degree of D is two.

6.1.2 Terminal and non-Terminal node


Node with degree zero is called a leaf node or terminal node; alternatively all other nodes
are called as non-terminal node. For example C, E, F, and G are leaf node of the tree and all
others are non- terminal nodes.

6.1.3 Children and parent node


The roots of the sub trees of a node X, are children of X and in turn X is the parents of its
children. Thus the children of D are F and G and the parent of D is A.

6.1.4 Siblings
Children of same parent are said to be siblings. For example B, C and D are siblings.

6.1.5 Ancestors
Ancestors of a node are the nodes above the path from the root to that node. For example ancestors of
F are D and A.

6.1.6 Degree of Trees


The degree of tree is the maximum degree of the node in the tree. Thus the degree of
above given tree is three.

6.1.7 Level of a node


The level of a node is defined by initially getting the root be at level 1. Note that if a node is at level l
then its children are at level l + 1.

2
Trees
ITE 2142 – Data Structures & Algorithms Week 06

6.1.8 Height or depth of a Tree


The height or depth is defined to be the maximum level of any node of the tree.

6.1.9 Forest
A forest is the set of disjoint trees. The notion of forest is very close to that of a tree because
if we remove the root of a tree we get the forest. For example if we remove the node A which
is the root node we get three forests.

6.2 Binary Tree


A binary tree is a tree in which each node has exactly two (possibly empty) sub trees called
left sub tree and right sub tree of the node. Clearly the degree of binary tree is less than or
equal to two. Thus tree consists of nodes connected by edges.

Node
edge

left Sub tree


Right Sub tree

3
Trees
ITE 2142 – Data Structures & Algorithms Week 06

Advantages of binary array combine advantages of two other structures: an ordered array
and a linked list. You can search a tree quickly as you can in an ordered array, and you can
also insert and delete items quickly, as you can with a linked list.

In computer programs, nodes often represent such entities as people, car parts, airline
reservations, and so on; in other works, the typical items we store in any kind of data
structure. In an OOP language such Java, these real-world entities are represented by
objects. The lines (edges) between the nodes represent the way the nodes are related.
Roughly speaking, the lines represent convenience: it’s easy for a program to get from one
node to another if there is a line connecting them. In fact, the only way to get from a node to
node is to follow a path along the lines. Generally you are restricted to going in one direction
along edges: i.e. from the root downward.

6.2.1 Binary Tree representation in Java


Let’s see how we can implement a binary tree in Java. As with other data structures, there
are several approaches for representing a tree in the computer’s memory. The most common
approach is to store the nodes at unrelated locations in memory and connect those using
references in each node that point to its children. It is also possible to represent a tree in
memory as an array, with nodes in specific positions stored in corresponding positions in
the array.

6.2.2 The Node class


First we need a class of node objects. These objects contain the data representing the objects
being stored (for an e.g. employees in an employee database) and also references to each of
the node’s two children. This is how it looks;

class Node
{
public int iData; // data item (key)
public double dData; // data item
public Node leftChild; // this node's left child public
Node rightChild; // this node's rightchild

4
Trees
ITE 2142 – Data Structures & Algorithms Week 06

public void displayNode() // display ourself


{
System.out.print('{');
System.out.print(iData);
System.out.print(", ");
System.out.print(dData);
System.out.print("} ");
}
} // end class Node

6.2.3 The Tree class

We will also need a class from which to instantiate the tree itself; the object that holds all
the nodes. We will call this class Tree. It has only one field: a node variable that holds the
root. It doesn’t need fields for the other nodes because they are all accessed from the root.
It has number of methods: some for finding, inserting deleting nodes, several for different
kinds of traverse and one to display the tree. Here’s a skeleton of the tree class.

class Tree
{
private Node root; // first node of tree

public Node find(int key) // find node with given key


{
}
public void insert(int id, double dd)
{
}
} // end class Tree

Next we will look at individual tree operations: finding a node, inserting a node, traversing
the tree and deleting a node.

6.2.4 Finding a node


Finding a node with a specific key is the simplest of the major tree operations, so let’s start
with that. Remember that the nodes in a binary search tree correspond to objects containing
information. They could be person’s objects, with an employee number as the key and also
5
Trees
ITE 2142 – Data Structures & Algorithms Week 06
perhaps name, address, telephone number, salary and other fields. Or they could represent
car parts, with a part number as the key value and fields for quantity on hand, price and so
on. Here’s how Java implementation looks like.

public Node find(int key) // find node with given key


{ // (assumes non-emptytree)
Node current = root; // start at root
while(current.iData != key) // while no match,
{
if(key < current.iData) // go left?
current = current.leftChild;
else // or go right?
current = current.rightChild;
if(current == null) // if no child,
return null; // didn't findit
}
return current; // found it
} // end find()

Consider the following binary tree and suppose that you want to find the node representing
item with key value 57. The finding process can be depicted as follows in Figure 6.1.

Figure 6.1 – Finding an element in a tree


6
Trees
ITE 2142 – Data Structures & Algorithms Week 06

This process can be explained as follows.


First compares the key value 57 with the value at root, which is 63. Since 57 is less than 63
it decides that desired node must be at the left side of the tree. The left child of the root has
value 27, so the comparison of 57 and 27 will show that the desired node is in the right sub
tree. So the arrow will go to 51. Then again 57 is greater than the 51 node, and desired node
is in the right sub tree. So the arrow will go to 58. Since 57 is less than the 58 node, and
desired node is in the left sub tree. So the arrow will go to 57. This time the comparison
shows 57 equals the node’s key value, so we have found the node we want. This ends the
finding process.

6.2.5 Inserting a Node


To insert a node we must find the place to insert it. We follow the path from the root to the
appropriate node, which will be the parent of the new node. Once this parent is found, the
new node is connected as its left or right child, depending on whether the new node’s key is
less than or greater than that of the parent. Here’s how Java implementation looks like.

7
Trees
ITE 2142 – Data Structures & Algorithms Week 06

public void insert(int id, double dd)


{
Node newNode = new Node(); // make new
node newNode.iData = id; // insert data
newNode.dData = dd;

if(root==null) // no node in
root root = newNode;
else // root occupied
{
Node current = root; // start atroot
Node parent;

while(true) // (exits internally)


{
parent = current;
if(id < current.iData) // go left?
{
current = current.leftChild;
if(current == null) // if end of the line,
{ // insert onleft
parent.leftChild = newNode;
return;
}
} // end if go left
else // or go right?
{
current = current.rightChild;
if(current == null) // if end of the line
{ // insert onright
parent.rightChild = newNode;
return;
}
} // end else go right
} // end while
} // end else not root
} // end insert()

Consider the following tree. Suppose that you want to insert an element 100. First
we find the appropriate node, which will be the parent of the new node. Following
the find method, we can find parent of new node as 92. So we can insert new node

8
Trees
ITE 2142 – Data Structures & Algorithms Week 06

as right child of 92.

After insertion we have tree like this.

9
Trees
ITE 2142 – Data Structures & Algorithms Week 06

6.3 Traversing the tree


Traversing a tree means visiting each node in a specified order. This process is not
as commonly used as finding and inserting nodes. One reason for this is that
traversal is not particularly fast. But traversing a tree is useful in some
circumstances and the algorithm is interesting. It’s needed when we want to print
the data values of the node or to search for a particular node or even just to count
nodes. For binary trees there are three main orders in which one might visit the node
during a tree traversal. Consider the following diagram.

L R

Figure 6.2 – ordering of a node

In this figure, N denotes a node. L and R denotes left and right sub trees of the node N,
now it’s ordering can be classified as,
6.3.1 Pre-order
That’s visit the node before each of left sub tree. i.e. root left right

10
Trees
ITE 2142 – Data Structures & Algorithms Week 06

For example consider the following tree.

Pre-order traversal results 63, 27,13, 51,80, 92, 82

This process can be implemented in Java as follows.


private void preOrder(Node localRoot)
// locaRoot is the reference to root node
{
if(localRoot != null)
{
localRoot.displayNode();
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild);
}
}

6.3.2 In-order
That’s visit node between visiting it’s subtrees. i.e. left root right
For example consider the following tree.

11
Trees
ITE 2142 – Data Structures & Algorithms Week 06

In-order traversal results 13,27,51,63,80,82,92


This process can be implemented in Java as follows.

private void inOrder(Node localRoot)


{
if(localRoot != null)
{
inOrder(localRoot.leftChild); localRoot.displayNode();
inOrder(localRoot.rightChild);
}
}

6.3.3 Post-order
That’s visit the node after visiting it’s sub trees. i. e. left right root
For example consider the following tree.

Post-order traversal results 13, 51, 27, 82,92,80,63


This process can be implemented in Java as follows.

private void postOrder(Node localRoot)


{
if(localRoot != null)
{
postOrder(localRoot.leftChild);
postOrder(localRoot.rightChild);
localRoot.displayNode();
}

12
Trees
ITE 2142 – Data Structures & Algorithms Week 06

Note: Obviously in-order traversal of a binary search tree is appropriate for dealing with its
value in sorted order.

Activity 6.1
Consider the following tree. What would be the output value if we traverse through the tree
using in -order traversal?

Activity 6.1 - Answer


0 2 3 4 24 49 68 72 75 77 78 87
88 90 95

6.4. Binary Heaps

A binary heap is a complete binary tree which satisfies the heap ordering property. The ordering
can be one of two types:

 the min-heap property: the value of each node is greater than or equal to the value of its
parent, with the minimum-value element at the root.
 the max-heap property: the value of each node is less than or equal to the value of its parent,
with the maximum-value element at the root.

13
Trees
ITE 2142 – Data Structures & Algorithms Week 06

Throughout this chapter the word "heap" will always refer to a min-heap. These types create two
different heap tree structures as shown in the following Figure 6.3.

Figure 6.3-a Min-heap tree Figure 6.3-b Max-heap tree

In a heap the highest (or lowest) priority element is always stored at the root, hence the name "heap".
A heap is not a sorted structure and can be regarded as partially ordered. As you see from the picture,
there is no particular relationship among nodes on any given level, even among the siblings.

Since a heap is a complete binary tree, it has a smallest possible height - a heap with N nodes always
has O(log N) height. A heap is useful data structure when you need to remove the object with the highest
(or lowest) priority. A common use of a heap is to implement a priority queue.

6.4.1 Implementation of Min Heap

A Min Heap is a Complete Binary Tree. A Min heap is typically represented as an array. The root
element will be at Arr[0]. For any ith node, i.e., Arr[i]:

Arr[(i -1) / 2] returns its parent node.

Arr[(2 * i) + 1] returns its left child node.

Arr[(2 * i) + 2] returns its right child node.

Operations on Min Heap:


1. getMin(): It returns the root element of Min Heap. Time Complexity of this operation is O(1).

14
Trees
ITE 2142 – Data Structures & Algorithms Week 06

2. extractMin(): Removes the minimum element from MinHeap. Time Complexity of this
Operation is O(Log n) as this operation needs to maintain the heap property (by calling
heapify()) after removing root.
3. insert(): Inserting a new key takes O(Log n) time. We add a new key at the end of the tree. If
new key is larger than its parent, then we don’t need to do anything. Otherwise, we need to
traverse up to fix the violated heap property.

Below is the implementation of Min Heap in Java

// Java implementation of Min Heap

public class MinHeap {


private int[] Heap;
private int size;
private int maxsize;

private static final int FRONT = 1;

public MinHeap(int maxsize)


{
this.maxsize = maxsize;
this.size = 0;
Heap = new int[this.maxsize + 1];
Heap[0] = Integer.MIN_VALUE;
}

// Function to return the position of the parent for the node currently
// at pos

private int parent(int pos)


{
return pos / 2;
}

// Function to return the position of the


// left child for the node currently at pos

private int leftChild(int pos)


{
return (2 * pos);
}

15
Trees
ITE 2142 – Data Structures & Algorithms Week 06

// Function to return the position of


// the right child for the node currently
// at pos

private int rightChild(int pos)


{
return (2 * pos) + 1;
}

// Function that returns true if the passed


// node is a leaf node
private boolean isLeaf(int pos)
{
if (pos >= (size / 2) && pos <= size) {
return true;
}
return false;
}

// Function to swap two nodes of the heap


private void swap(int fpos, int spos)
{
int tmp;
tmp = Heap[fpos];
Heap[fpos] = Heap[spos];
Heap[spos] = tmp;
}

// Function to heapify the node at pos


private void minHeapify(int pos)
{

// If the node is a non-leaf node and greater


// than any of its child
if (!isLeaf(pos)) {
if (Heap[pos] > Heap[leftChild(pos)]
|| Heap[pos] > Heap[rightChild(pos)]) {

// Swap with the left child and heapify


// the left child
if (Heap[leftChild(pos)] < Heap[rightChild(pos)]) {
swap(pos, leftChild(pos));
minHeapify(leftChild(pos));
}

// Swap with the right child and heapify


// the right child
else {
swap(pos, rightChild(pos));
minHeapify(rightChild(pos));
}
}
}
}

16
Trees
ITE 2142 – Data Structures & Algorithms Week 06

// Function to insert a node into the heap


public void insert(int element)
{
Heap[++size] = element;
int current = size;

while (Heap[current] < Heap[parent(current)]) {


swap(current, parent(current));
current = parent(current);
}
}

// Function to print the contents of the heap


public void print()
{
for (int i = 1; i <= size / 2; i++) {
System.out.print(" PARENT : " + Heap[i]
+ " LEFT CHILD : " + Heap[2 * i]
+ " RIGHT CHILD :" + Heap[2 * i + 1]);
System.out.println();
}
}

// Function to build the min heap using


// the minHeapify
public void minHeap()
{
for (int pos = (size / 2); pos >= 1; pos--) {
minHeapify(pos);
}
}

// Function to remove and return the minimum


// element from the heap
public int remove()
{
int popped = Heap[FRONT];
Heap[FRONT] = Heap[size--];
minHeapify(FRONT);
return popped;
}

17
Trees
ITE 2142 – Data Structures & Algorithms Week 06

// Driver code
public static void main(String[] arg)
{
System.out.println("The Min Heap is ");
MinHeap minHeap = new MinHeap(15);
minHeap.insert(5);
minHeap.insert(3);
minHeap.insert(17);
minHeap.insert(10);
minHeap.insert(84);
minHeap.insert(19);
minHeap.insert(6);
minHeap.insert(22);
minHeap.insert(9);
minHeap.minHeap();

minHeap.print();
System.out.println("The Min val is " + minHeap.remove());
}
}

6.4.1 Implementation of Max Heap

A Max Heap is a Complete Binary Tree. A Max heap is typically represented as an array. The root
element will be at Arr[0]. Below table shows indexes of other nodes for the ith node, i.e., Arr[i]:
Arr[(i-1)/2] Returns the parent node.
Arr[(2*i)+1] Returns the left child node.
Arr[(2*i)+2] Returns the right child node.

Operations on Max Heap:


1) getMax(): It returns the root element of Max Heap. Time Complexity of this operation is O(1).

2) extractMax(): Removes the maximum element from MaxHeap. Time Complexity of this Operation
is O(Log n) as this operation needs to maintain the heap property (by calling heapify()) after removing
root.

4) insert(): Inserting a new key takes O(Log n) time. We add a new key at the end of the tree. If new

18
Trees
ITE 2142 – Data Structures & Algorithms Week 06

key is smaller than its parent, then we don’t need to do anything. Otherwise, we need to traverse up to
fix the violated heap property.

Note : In below implementation, we do indexing from index 1 to simplify the implementation.

// Java program to implement Max Heap


public class MaxHeap {
private int[] Heap;
private int size;
private int maxsize;

// Constructor to initialize an
// empty max heap with given maximum
// capacity.
public MaxHeap(int maxsize)
{
this.maxsize = maxsize;
this.size = 0;
Heap = new int[this.maxsize + 1];
Heap[0] = Integer.MAX_VALUE;
}

// Returns position of parent


private int parent(int pos)
{
return pos / 2;
}

19
Trees
ITE 2142 – Data Structures & Algorithms Week 06

// Below two functions return left and


// right children.
private int leftChild(int pos)
{
return (2 * pos);
}
private int rightChild(int pos)
{
return (2 * pos) + 1;
}

// Returns true of given node is leaf


private boolean isLeaf(int pos)
{
if (pos >= (size / 2) && pos <= size) {
return true;
}
return false;
}

private void swap(int fpos, int spos)


{
int tmp;
tmp = Heap[fpos];
Heap[fpos] = Heap[spos];
Heap[spos] = tmp;
}

20
Trees
ITE 2142 – Data Structures & Algorithms Week 06

// A recursive function to max heapify the given subtree. This function assumes that the left and
// right subtrees are already heapified, we only need to fix the root.
private void maxHeapify(int pos)
{
if (isLeaf(pos))
return;
if (Heap[pos] < Heap[leftChild(pos)] ||
Heap[pos] < Heap[rightChild(pos)]) {

if (Heap[leftChild(pos)] > Heap[rightChild(pos)]) {


swap(pos, leftChild(pos));
maxHeapify(leftChild(pos));
}
else {
swap(pos, rightChild(pos));
maxHeapify(rightChild(pos));
}
}
}

// Inserts a new element to max heap


public void insert(int element)
{
Heap[++size] = element;
// Traverse up and fix violated property
int current = size;
while (Heap[current] > Heap[parent(current)]) {
swap(current, parent(current));
current = parent(current);
}
}
21
Trees
ITE 2142 – Data Structures & Algorithms Week 06

public void print()


{
for (int i = 1; i <= size / 2; i++) {
System.out.print(" PARENT : " + Heap[i] + " LEFT CHILD : " +
Heap[2 * i] + " RIGHT CHILD :" + Heap[2 * i + 1]);
System.out.println();
}
}

// Remove an element from max heap


public int extractMax()
{
int popped = Heap[1];
Heap[1] = Heap[size--];
maxHeapify(1);
return popped;
}

public static void main(String[] arg) {


System.out.println("The Max Heap is ");
MaxHeap maxHeap = new MaxHeap(15);
maxHeap.insert(5);
maxHeap.insert(3);
maxHeap.insert(17);
maxHeap.insert(10);
maxHeap.insert(84);
maxHeap.insert(19);
maxHeap.print();
System.out.println("The max val is " + maxHeap.extractMax());
}
}
22
Trees
ITE 2142 – Data Structures & Algorithms Week 06

Summary
In this lesson you have learnt about Trees. You learnt how to traverse through a tree, how to
implement trees and perform tree operations in Java programming language. You learnt about
different types of tree data structure including Heap trees. Next lesson we will learn about
graph data structure.

23
Trees

You might also like