Data Structure and Algorithms - Tree: Important Terms

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 19

Data Structure and Algorithms - Tree

Tree represents the nodes connected by edges. Binary Tree is a special data structure
used for data storage purposes. A binary tree has a special condition that each node can
have a maximum of two children. A binary tree has the benefits of both an ordered array
and a linked list as search is as quick as in a sorted array and insertion or deletion
operation are as fast as in linked list.

Important Terms
Following are the important terms with respect to tree.
 Path − Path refers to the sequence of nodes along the edges of a tree.
 Root − The node at the top of the tree is called root. There is only one root per tree
and one path from the root node to any node.
 Parent − Any node except the root node has one edge upward to a node called
parent.
 Child − The node below a given node connected by its edge downward is called its
child node.
 Leaf − The node which does not have any child node is called the leaf node.
 Subtree − Subtree represents the descendants of a node.
 Visiting − Visiting refers to checking the value of a node when control is on the
node.
 Traversing − Traversing means passing through nodes in a specific order.
 Levels − Level of a node represents the generation of a node. If the root node is at
level 0, then its next child node is at level 1, its grandchild is at level 2, and so on.
 keys − Key represents a value of a node based on which a search operation is to
be carried out for a node.

Binary Search Tree Representation

Binary Search tree exhibits a special behavior. A node's left child must have a value less
than its parent's value and the node's right child must have a value greater than its parent
value.

Tree Node
The code to write a tree node would be similar to what is given below. It has a data part
and references to its left and right child nodes.

struct node {
int data;
struct node *leftChild;
struct node *rightChild;
};
In a tree, all nodes share common construct.

BST Basic Operations


The basic operations that can be performed on a binary search tree data structure, are
the following −
 Insert − Inserts an element in a tree/create a tree.
 Search − Searches an element in a tree.
 Preorder Traversal − Traverses a tree in a pre-order manner.
 Inorder Traversal − Traverses a tree in an in-order manner.
 Postorder Traversal − Traverses a tree in a post-order manner.

Insert Operation
The very first insertion creates the tree. Afterwards, whenever an element is to be
inserted, first locate its proper location. Start searching from the root node, then if the data
is less than the key value, search for the empty location in the left subtree and insert the
data. Otherwise, search for the empty location in the right subtree and insert the data.
Algorithm

If root is NULL
then create root node
return

If root exists then


compare the data with node.data

while until insertion position is located

If data is greater than node.data


goto right subtree
else
goto left subtree

endwhile

insert data

end If

The implementation of insert function should look like this −

void insert(int data) {


struct node *tempNode = (struct node*) malloc(sizeof(struct node));
struct node *current;
struct node *parent;

tempNode->data = data;
tempNode->leftChild = NULL;
tempNode->rightChild = NULL;

//if tree is empty, create root node


if(root == NULL) {
root = tempNode;
} else {
current = root;
parent = NULL;

while(1) {
parent = current;

//go to left of the tree


if(data < parent->data) {
current = current->leftChild;

//insert to the left


if(current == NULL) {
parent->leftChild = tempNode;
return;
}
}

//go to right of the tree


else {
current = current->rightChild;

//insert to the right


if(current == NULL) {
parent->rightChild = tempNode;
return;
}
}
}
}
}
Search Operation
Whenever an element is to be searched, start searching from the root node, then if the
data is less than the key value, search for the element in the left subtree. Otherwise,
search for the element in the right subtree. Follow the same algorithm for each node.

Algorithm

If root.data is equal to search.data


return root
else
while data not found

If data is greater than node.data


goto right subtree
else
goto left subtree

If data found
return node

endwhile

return data not found

end if
The implementation of this algorithm should look like this.

struct node* search(int data) {


struct node *current = root;
printf("Visiting elements: ");

while(current->data != data) {
if(current != NULL)
printf("%d ",current->data);
//go to left tree

if(current->data > data) {


current = current->leftChild;
}
//else go to right tree
else {
current = current->rightChild;
}

//not found
if(current == NULL) {
return NULL;
}

return current;
}
}

gle+Dat Tree Traversal


Traversal is a process to visit all the nodes of a tree and may print their values too. Because,
all nodes are connected via edges (links) we always start from the root (head) node. That is,
we cannot randomly access a node in a tree. There are three ways which we use to traverse a
tree −

 In-order Traversal
 Pre-order Traversal
 Post-order Traversal
Generally, we traverse a tree to search or locate a given item or key in the tree or to print all
the values it contains.

In-order Traversal
In this traversal method, the left subtree is visited first, then the root and later the right sub-tree.
We should always remember that every node may represent a subtree itself.
If a binary tree is traversed in-order, the output will produce sorted key values in an ascending
order.
o We start from A, and following in-order traversal, we move to its left subtree B. B is also traversed in-order
The process goes on until all the nodes are visited. The output of inorder traversal of this tree will be −
o D→B→E→A→F→C→G
orithm
Until all nodes are traversed −
o Step 1 − Recursively traverse left subtree.
o Step 2 − Visit root node.
o Step 3 − Recursively traverse right subtree.
Pre-order Traversal : In this traversal method, the root node is visited first, then the left subtree
and finally the right subtree.

We start from A, and following pre-order traversal, we first visit A itself and then move to its left
subtree B. B is also traversed pre-order. The process goes on until all the nodes are visited.
The output of pre-order traversal of this tree will be −
A→B→D→E→C→F→G
Algorithm
Until all nodes are traversed −
Step 1 − Visit root node.
Step 2 − Recursively traverse left subtree.
Step 3 − Recursively traverse right subtree.
Post-order Traversal
In this traversal method, the root node is visited last, hence the name. First we traverse the left
subtree, then the right subtree and finally the root node.

We start from A, and following Post-order traversal, we first visit the left subtree B. B is also
traversed post-order. The process goes on until all the nodes are visited. The output of post-
order traversal of this tree will be −
D→E→B→F→G→C→A
Algorithm

Until all nodes are traversed −


Step 1 − Recursively traverse left subtree.
Step 2 − Recursively traverse right subtree.
Step 3 − Visit root node.
Tree Traversals

(Inorder, Preorder and Postorder)


Unlike linear data structures (Array, Linked List, Queues, Stacks, etc)
which have only one logical way to traverse them, trees can be traversed
in different ways. Following are the generally used ways for traversing
trees.

Example Tree

Depth First Traversals:


(a)Inorder (Left, Root, Right) : 4 2 5 1 3
(b)Preorder (Root, Left, Right) : 1 2 4 5 3
(c) Postorder (Left, Right, Root) : 4 5 2 3 1
Breadth First or Level Order Traversal : 1 2 3 4 5
Please see this post for Breadth First Traversal.
Inorder Traversal:
Algorithm Inorder(tree)
1. Traverse the left subtree, i.e., call Inorder(left-subtree)
2. Visit the root.
3. Traverse the right subtree, i.e., call Inorder(right-subtree)
Uses of Inorder

In case of binary search trees (BST), Inorder traversal gives nodes in non-
decreasing order. To get nodes of BST in non-increasing order, a variation
of Inorder traversal where Inorder itraversal s reversed, can be used.
Example: Inorder traversal for the above given figure is 4 2 5 1 3.

Preorder Traversal:
Algorithm Preorder(tree)
1. Visit the root.
2. Traverse the left subtree, i.e., call Preorder(left-subtree)
3. Traverse the right subtree, i.e., call Preorder(right-subtree)
Uses of Preorder

Preorder traversal is used to create a copy of the tree. Preorder traversal


is also used to get prefix expression on of an expression tree.
Example: Preorder traversal for the above given figure is 1 2 4 5 3.

Postorder Traversal:
Algorithm Postorder(tree)
1. Traverse the left subtree, i.e., call Postorder(left-subtree)
2. Traverse the right subtree, i.e., call Postorder(right-subtree)
3. Visit the root.
Uses of Postorder
Postorder traversal is used to delete the tree.

Postorder traversal is also useful to get the postfix expression of an


expression tree.

Example: Postorder traversal for the above given figure is 4 5 2 3 1.

// C program for different tree traversals


#include <stdio.h>
#include <stdlib.h>

/* A binary tree node has data, pointer to left child


and a pointer to right child */
struct node
{
int data;
struct node* left;
struct node* right;
};

/* Helper function that allocates a new node with the


given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;

return(node);
}

/* Given a binary tree, print its nodes according to


the
"bottom-up" postorder traversal. */
void printPostorder(struct node* node)
{
if (node == NULL)
return;

// first recur on left subtree


printPostorder(node->left);

// then recur on right subtree


printPostorder(node->right);

// now deal with the node


printf("%d ", node->data);
}
/* Given a binary tree, print its nodes in inorder*/
void printInorder(struct node* node)
{
if (node == NULL)
return;

/* first recur on left child */


printInorder(node->left);

/* then print the data of node */


printf("%d ", node->data);

/* now recur on right child */


printInorder(node->right);
}

/* Given a binary tree, print its nodes in preorder*/


void printPreorder(struct node* node)
{
if (node == NULL)
return;

/* first print data of node */


printf("%d ", node->data);

/* then recur on left sutree */


printPreorder(node->left);

/* now recur on right subtree */


printPreorder(node->right);
}

/* Driver program to test above functions*/


int main()
{
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);

printf("\nPreorder traversal of binary tree is \n");


printPreorder(root);

printf("\nInorder traversal of binary tree is \n");


printInorder(root);

printf("\nPostorder traversal of binary tree is \n");


printPostorder(root);

getchar();
return 0;
}

Output:
Preorder traversal of binary tree is
12453
Inorder traversal of binary tree is
42513
Postorder traversal of binary tree is
45231
Threaded Binary Tree
Inorder traversal of a Binary tree is either be done using recursion or with the
use of a auxiliary stack. The idea of threaded binary trees is to make inorder
traversal faster and do it without stack and without recursion. A binary tree is
made threaded by making all right child pointers that would normally be NULL
point to the inorder successor of the node (if it exists).
There are two types of threaded binary trees.
Single Threaded:
Where a NULL right pointers is made to point to the inorder successor (if
successor exists)
Double Threaded:
Where both left and right NULL pointers are made to point to inorder
predecessor and inorder successor respectively. The predecessor threads
are useful for reverse inorder traversal and postorder traversal.
The threads are also useful for fast accessing ancestors of a node.
Following diagram shows an example Single Threaded Binary Tree. The
dotted lines represent threads.
Node *left, *right;
bool rightThread;
}
Since right pointer is used for two purposes, the boolean variable rightThread is used to
indicate whether right pointer points to right child or inorder successor. Similarly, we can
add leftThread for a double threaded binary tree.

Inorder Taversal using Threads

// Utility function to find leftmost node in a tree


rooted with n
struct Node* leftMost(struct Node *n)
{
if (n == NULL)
return NULL;

while (n->left != NULL)


n = n->left;

return n;
}

// C code to do inorder traversal in a threaded


binary tree
void inOrder(struct Node *root)
{
struct Node *cur = leftmost(root);
while (cur != NULL)
{
printf("%d ", cur->data);

// If this node is a thread node, then go to


// inorder successor
if (cur->rightThread)
cur = cur->rightThread;
else // Else go to the leftmost child in
right subtree
cur = leftmost(cur->right);
}
}
Heap

In computer science, a heap is a specialized tree-based data structure that satisfies


the heap property:
If P is a parent node of C, then the key (the value) of P is either greater than or equal to
(in a max heap) or less than or equal to (in a min heap) the key of C. The node at the
"top" of the heap (with no parents) ..
In a heap is a specialized tree-based data structure that satisfies the heap property: if
P is a parent node of C, then the key (the value) of P is either greater than or equal to
(in a max heap) or less than or equal to (in a min heap) the key of C.[1] The node at the
"top" of the heap (with no parents) is called the root node.
Heap is a special case of balanced binary tree data structure where the
root-node key is compared with its children and arranged accordingly.
If α has child node β then −
key(α) ≥ key(β)
As the value of parent is greater than that of child, this property
generates Max Heap. Based on this criteria, a heap can be of two types

For Input → 35 33 42 10 14 19 27 44 26 31

Min-Heap − Where the value of the root node is less than or equal to
either of its children.

Max-Heap − Where the value of the root node is greater than or equal to
either of its children.
Both trees are constructed using the same input and order of arrival.
.
We will soon be discussing insertion and deletion in threaded binary trees.
Sources:
http://en.wikipedia.org/wiki/Threaded_binary_tree
www.cs.berkeley.edu/~kamil/teaching/su02/080802.ppt

You might also like