Unite 2 and 3 and 4
Unite 2 and 3 and 4
When the function is invoked from any part of the program, it all
executes the codes defined in the body of the function.
{
cout << "Hello World";
}
Here,
the name of the function is greet()
the return type of the function is void
the empty parentheses mean it doesn't have any
parameters
the function body is written inside {}
Note: We will learn about returnType and parameters later in
this tutorial.
Calling a Function
void main()
{
}
How Function works in C++
{
cout << "Hello there!";
}
void main()
{
getch();
}
Output
Hello there!
Function Parameters
getch();
}
Example 2: Function with Parameters
// program to print a text
#include <iostream.h>
#include<conio.h>
void displayNum(int n1, float n2) // display a number
{
cout << "The int number is " << n1;
cout << "The double number is " << n2;
}
void main()
{
int num1 = 5;
double num2 = 5.5;
displayNum(num1, num2); // calling the function
getch();
}
Output
The int number is 5
The double number is 5.5
Return Statement
void displayNumber()
{
// code
}
This means the function is not returning any value.
It's also possible to return a value from a function. For this, we
need to specify the returnType of the function during function
declaration.
For example,
int add (int a, int b)
{
return (a + b);
}
Here, we have the data type int instead of void. This means
that the function returns an int value.
The code return (a + b); returns the sum of the two parameters
as the function value.
The return statement denotes that the function has ended. Any
code after return inside the function is not executed.
Example 3: Add Two Numbers
// program to add two numbers using a function
#include <iostream>
// declaring a function
int add(int a, int b)
{
return (a + b);
}
int main()
{
int sum;
return 0;
}
Output
100 + 78 = 178
In the above program, the add() function is used to find the sum
of two numbers.
We pass two int literals 100 and 78 while calling the function.
We store the returned value of the function in the variable sum,
and then we print it.
Working of C++ Function with return statement
Function Prototype
// function prototype
void add(int, int);
void main()
{
// calling the function before declaration.
add(5, 3);
return 0;
}
// function definition
void add(int a, int b)
{
cout << (a + b);
}
In the above code, the function prototype is:
void add(int, int);
#include <iostream.h>
#include<conio.h>
// function prototype
int add(int, int);
void main()
{
int sum;
sum = add(100, 78); // calling the function and storing
cout << "100 + 78 = " << sum << endl; // the returned value in sum
getch();
}
// function definition
int add(int a, int b)
{
return (a + b);
}
Output
100 + 78 = 178
int main()
{
// No argument is passed to prime()
prime();
return 0;
}// Return type of function is void because value is not returned.
void prime()
{
if (flag == 1)
{
cout << num << " is not a prime number.";
}
else
{
cout << num << " is a prime number.";
}
}
In the above program, prime() is called from the main() with no
arguments.
prime() takes the positive number from the user and checks
whether the number is a prime number or not.
Since, return type of prime() is void, no value is returned from
the function.
int main()
{
int num, i, flag = 0;
if (flag == 1)
{
cout<<num<<" is not a prime number.";
}
else
{
cout<<num<<" is a prime number.";
}
return 0;
}// Return type of function is int
int prime()
{
int n;
return n;
}
In the above program, prime() function is called from
the main() with no arguments.
prime() takes a positive integer from the user. Since, return
type of the function is an int, it returns the inputted number from
the user back to the calling main() function.
Then, whether the number is prime or not is checked in the
main() itself and printed onto the screen.
int main()
{
int num;
cout << "Enter a positive integer to check: ";
cin >> num;
if (flag == 1)
{
cout << n << " is not a prime number.";
}
else {
cout << n << " is a prime number.";
}
}
In the above program, positive number is first asked from the
user which is stored in the variable num.
Then, num is passed to the prime() function where, whether the
number is prime or not is checked and printed.
Since, the return type of prime() is a void, no value is returned
from the function.
Example 4: Arguments passed and a return value.
#include <iostream.h>
#include<conio.h>
int prime(int n);
void main()
{
int num, flag = 0;
cout << "Enter positive integer to check: ";
cin >> num;
if(flag == 1)
cout << num << " is not a prime number.";
else
cout<< num << " is a prime number.";
getch();
}
return 0;
}
In the above program, a positive integer is asked from the user
and stored in the variable num.
Then, num is passed to the function prime() where, whether the
number is prime or not is checked.
Since, the return type of prime() is an int, 1 or 0 is returned to
the main() calling function. If the number is a prime number, 1
is returned. If not, 0 is returned.
Back in the main() function, the returned 1 or 0 is stored in the
variable flag, and the corresponding text is printed onto the
screen.
void main()
{
double number, squareRoot;
number = 25.0;
// sqrt() is a library function to calculate the square root
squareRoot = sqrt(number);
cout << "Square root of " << number << " = " << squareRoot;
getch();
}
Output
Square root of 25 = 5
#include <iostream.h>
#include<conio.h>
Void main()
{
int test[3][2] = {{2, -5},{4, 0},{9, 1}};
// use of nested for loop
// access rows of the array
for (int i = 0; i < 3; ++i)
{
// access columns of the array
for (int j = 0; j < 2; ++j)
{
cout << "test[" << i << "][" << j << "] = " << test[i][j] << endl;
}
}
getch();
}
Run Code
Output
test[0][0] = 2
test[0][1] = -5
test[1][0] = 4
test[1][1] = 0
test[2][0] = 9
test[2][1] = 1
In the above example, we have initialized a two-
dimensional int array named test that has 3 "rows" and 2
"columns".
Here, we have used the nested for loop to display the array
elements.
the outer loop from i == 0 to i == 2 access the rows of the
array
the inner loop from j == 0 to j == 1 access the columns of the
array
Finally, we print the array elements in each iteration.
#include <iostream.h>
#include<conio.h>
Void main()
{
// declare function to display marks
// take a 1d array as parameter
void display(int m[5])
{
cout << "Displaying marks: " << endl;
Void main()
{
getch();
}
Run Code
Output
Displaying marks:
Student 1: 88
Student 2: 76
Student 3: 90
Student 4: 61
Student 5: 69
Here,
When we call a function by passing an array as the
argument, only the name of the array is used.
display(marks);
Here, the argument marks represent the memory address of
the first element of array marks[5].
However, notice the parameter of the display() function.
void display(int m[5])
Here, we use the full declaration of the array in the function
parameter, including the square braces [].
The function parameter int m[5] converts to int* m;. This
points to the same address pointed by the array marks. This
means that when we manipulate m[5] in the function body,
we are actually manipulating the original array marks.
C++ Structs
In C++, classes and structs are blueprints that are used to
create the instance of a class. Structs are used for
lightweight objects such as Rectangle, color, Point, etc.
Student s;
For example:
s.id = 4;
In linear data structures, the elements are arranged in sequence one after
the other. Since elements are arranged in particular order, they are easy to
implement.
However, when the complexity of the program increases, the linear data
structures might not be the best choice because of operational
complexities.
Popular linear data structures are:
1. Array Data Structure
In stack data structure, elements are stored in the LIFO principle. That is,
the last element stored in a stack will be removed first.
It works just like a pile of plates where the last plate kept on the pile will be
removed first. To learn more, visit Stack Data Structure.
In a stack, operations can be perform only from one end (top here).
3. Queue Data Structure
Unlike stack, the queue data structure works in the FIFO principle where
first element stored in the queue will be removed first.
It works just like a queue of people in the ticket counter where first person
on the queue will get the ticket first. To learn more, visit Queue Data
Structure.
In linked list data structure, data elements are connected through a series
of nodes. And, each node contains the data items and address to the next
node.
A linked list
Non linear data structures
Unlike linear data structures, elements in non-linear data structures are not
in any sequence. Instead they are arranged in a hierarchical manner where
one element will be connected to one or more elements.
Non-linear data structures are further divided into graph and tree based
data structures.
In graph data structure, each node is called vertex and each vertex is
connected to other vertices through edges.
Now that we know about linear and non-linear data structures, let's see the
major differences between them.
The data items are arranged in sequential The data items are arranged in non-
order, one after the other. sequential order (hierarchical manner).
All the items are present on the single The data items are present at different
layer. layers.
It can be traversed on a single run. That is, It requires multiple runs. That is, if we
if we start from the first element, we can start from the first element it might not
traverse all the elements sequentially in a be possible to traverse all the elements
single pass. in a single pass.
The time complexity increase with the data Time complexity remains the same.
size.
Data structure is a method of organizing a large amount of data more efficiently so that
any operation on that data becomes easy
Based on the organizing method of data structure, data structures are divided into two types.
Example
1. Arrays
2. List (Linked List)
3. Stack
4. Queue
Example
1. Tree
2. Graph
3. Dictionaries
4. Heaps
5. Tries, Etc.,
What is a Stack?
Stack is a linear data structure in which the insertion and deletion operations are performed at
only one end. In a stack, adding and removing of elements are performed at a single position
which is known as "top". That means, a new element is added at top of the stack and an element
is removed from the top of the stack. In stack, the insertion and deletion operations are
performed based on LIFO (Last In First Out) principle.
Operations on a Stack
The following operations are performed on the stack...
1. Using Array
2. Using Linked List
Step 1 - Include all the header files which are used in the
program and define a constant 'SIZE' with specific value.
Step 2 - Declare all the functions used in stack
implementation.
Step 3 - Create a one dimensional array with fixed size (int
stack[SIZE])
Step 4 - Define a integer variable 'top' and initialize with '-
1'. (int top = -1)
Step 5 - In main method, display menu with list of
operations and make suitable function calls to perform
operation selected by the user on the stack.
push(value) - Inserting value into the stack
What is an Expression?
Expression Types
Infix Expression
Postfix Expression
Prefix Expression
Infix Expression
In infix expression, operator is used in between the operands.
Example
Postfix Expression
Example
Prefix Expression
Example
Example
D=A+B*C
DABC*+=
If the reading symbol is right parenthesis ')', then Pop all the
contents of stack until respective left parenthesis is poped and
print each poped symbol to the result.
Example
(A+B)*(C-D)
AB+CD-*
after the operands. That means, in a postfix expression the operator follows the operands.
Example
A postfix expression can be evaluated using the Stack data structure. To evaluate a postfix
expression using Stack data structure we can use the following steps...
1. Read all the symbols one by one from left to right in the given Postfix Expression
operations and store the two popped oparands in two different variables (operand1
and operand2). Then perform reading symbol operation using operand1 and
4. Finally! perform a pop operation and display the popped value as final result.
Example
Example
Operations on a Queue
Using Array
Step 1 - Include all the header files which are used in the program and
define a constant 'SIZE' with specific value.
Step 2 - Declare all the user defined functions which are used in queue
implementation.
Step 3 - Create a one dimensional array with above defined SIZE (int
queue[SIZE])
Step 4 - Define two integer variables 'front' and 'rear' and initialize both
with '-1'. (int front = -1, rear = -1)
Step 5 - Then implement main method by displaying menu of operations
list and make suitable function calls to perform operation selected by the
user on queue.
Step 3 - If it is NOT EMPTY, then increment the front value by one (front
++). Then display queue[front] as deleted element. Then check whether
both front and rear are equal (front == rear), if it TRUE, then set
both front and rear to '-1' (front = rear = -1).
Step 3 - If it is NOT EMPTY, then define an integer variable 'i' and set
'i = front+1'.
Step 4 - Display 'queue[i]' value and increment 'i' value by one (i++).
Repeat the same until 'i' value reaches to rear (i <= rear)
Now consider the following situation after deleting three elements from
the queue...
This situation also says that Queue is Full and we cannot insert the new
element because 'rear' is still at last position. In the above situation, even
though we have empty positions in the queue we can not make use of
them to insert the new element. This is the major problem in a normal
queue data structure. To overcome this problem we use a circular queue
data structure.
Step 3 - Create a one dimensional array with above defined SIZE (int
cQueue[SIZE])
Step 4 - Define two integer variables 'front' and 'rear' and initialize both
with '-1'. (int front = -1, rear = -1)
Step 3 - If it is NOT EMPTY, then define an integer variable 'i' and set
'i = front'.
Step 4 - Check whether 'front <= rear', if it is TRUE, then display
'queue[i]' value and increment 'i' value by one (i++). Repeat the same
until 'i <= rear' becomes FALSE.
Step 5 - If 'front <= rear' is FALSE, then display 'queue[i]' value and
increment 'i' value by one (i++). Repeat the same until'i <= SIZE - 1'
becomes FALSE.
Step 6 - Set i to 0.
Tree - Terminology
Example
Terminology
1. Root
In a tree data structure, the first node is called as Root Node. Every tree
must have a root node. We can say that the root node is the origin of the
tree data structure. In any tree, there must be only one root node. We
never have multiple root nodes in a tree.
2. Edge
In a tree data structure, the connecting link between any two nodes is
called as EDGE. In a tree with 'N' number of nodes there will be a
maximum of 'N-1' number of edges.
3. Parent
4. Child
In a tree data structure, nodes which belong to same Parent are called
as SIBLINGS. In simple words, the nodes with the same parent are called
Sibling nodes.
6. Leaf
In a tree data structure, the node which does not have a child is called
as LEAF Node. In simple words, a leaf is a node with no child.
In a tree data structure, the leaf nodes are also called as External Nodes.
External node is also a node with no child. In a tree, leaf node is also
called as 'Terminal' node.
7. Internal Nodes
In a tree data structure, the node which has atleast one child is called
as INTERNAL Node. In simple words, an internal node is a node with
atleast one child.
In a tree data structure, nodes other than leaf nodes are called
as Internal Nodes. The root node is also said to be Internal Node if the tree
has more than one node. Internal nodes are also called as 'Non-Terminal'
nodes.
8. Degree
9. Level
In a tree data structure, the root node is said to be at Level 0 and the
children of root node are at Level 1 and the children of the nodes which
are at Level 1 will be at Level 2 and so on... In simple words, in a tree
each step from top to bottom is called as a Level and the Level count
starts with '0' and incremented by one at each level (Step).
10. Height
In a tree data structure, the total number of edges from leaf node to a
particular node in the longest path is called as HEIGHT of that Node. In a
tree, height of the root node is said to be height of the tree. In a
tree, height of all leaf nodes is '0'.
11. Depth
In a tree data structure, the total number of egdes from root node to a
particular node is called as DEPTH of that Node. In a tree, the total
number of edges from root node to a leaf node in the longest path is said
to be Depth of the tree. In simple words, the highest depth of any leaf
node in a tree is said to be depth of that tree. In a tree, depth of the root
node is '0'.
12. Path
In a tree data structure, the sequence of Nodes and Edges from one
node to another node is called as PATH between that two Nodes. Length
of a Path is total number of nodes in that path. In below example the path
A - B - E - J has length 4.
13. Sub Tree
ree Representations
List Representation
In this representation, we use a list with one type of node which consists
of three fields namely Data field, Left child reference field and Right
sibling reference field. Data field stores the actual value of a node, left
reference field stores the address of the left child and right reference
field stores the address of the right sibling node. Graphical
representation of that node is as follows...
In this representation, every node's data field stores the actual value of
that node. If that node has left a child, then left reference field stores the
address of that left child node otherwise stores NULL. If that node has
the right sibling, then right reference field stores the address of right
sibling node otherwise stores NULL.
The above example tree can be represented using Left Child - Right
Sibling representation as follows...
Binary Tree Datastructure
In a normal tree, every node can have any number of children. A binary
tree is a special type of tree data structure in which every node can have
a maximum of 2 children. One is known as a left child and the other is
known as right child.
A tree in which every node can have a maximum of two children is called
Binary Tree.
Example
There are different types of binary trees and they are...
In a binary tree, every node can have a maximum of two children. But in
strictly binary tree, every node should have exactly two children or none.
That means every internal node must have exactly two children. A
strictly Binary Tree can be defined as follows...
A binary tree in which every node has either two or zero number of
children is called Strictly Binary Tree
Strictly binary tree is also called as Full Binary Tree or Proper Binary
Tree or 2-Tree
Strictly binary tree data structure is used to represent mathematical
expressions.
Example
In a binary tree, every node can have a maximum of two children. But in
strictly binary tree, every node should have exactly two children or none
and in complete binary tree all the nodes must have exactly two children
and at every level of complete binary tree there must be 2level number
of nodes. For example at level 2 there must be 22 = 4 nodes and at level
3 there must be 23 = 8 nodes.
A binary tree in which every internal node has exactly two children and
all leaf nodes are at same level is called Complete Binary Tree.
A binary tree can be converted into Full Binary tree by adding dummy
nodes to existing nodes wherever required.
The full binary tree obtained by adding dummy nodes to a binary tree is
called as Extended Binary Tree.
In above figure, a normal binary tree is converted into full binary tree by
adding dummy nodes (In pink colour).
Array Representation
In - Order Traversal
In In-Order traversal, the root node is visited between the left child and
right child. In this traversal, the left child node is visited first, then the root
node is visited and later we go for visiting the right child node. This in-
order traversal is applicable for every root node of all subtrees in the
tree. This is performed recursively for all nodes in the tree.
In the above example of a binary tree, first we try to visit left child of root
node 'A', but A's left child 'B' is a root node for left subtree. so we try to
visit its (B's) left child 'D' and again D is a root for subtree with nodes D, I
and J. So we try to visit its left child 'I' and it is the leftmost child. So first
we visit 'I' then go for its root node 'D' and later we visit D's right child 'J'.
With this we have completed the left part of node B. Then visit 'B' and
next B's right child 'F' is visited. With this we have completed left part of
node A. Then visit root node 'A'. With this we have completed left and
root parts of node A. Then we go for the right part of the node A. In right
of A again there is a subtree with root C. So go for left child of C and
again it is a subtree with root G. But G does not have left part so we
visit 'G' and then visit G's right child K. With this we have completed the
left part of node C. Then visit root node 'C' and next visit C's right
child 'H' which is the rightmost child in the tree. So we stop the process.
I-D-J-B-F-A-G-K-C-H
In Pre-Order traversal, the root node is visited before the left child and
right child nodes. In this traversal, the root node is visited first, then its
left child and later its right child. This pre-order traversal is applicable for
every root node of all subtrees in the tree.
In the above example of binary tree, first we visit root node 'A' then visit
its left child 'B' which is a root for D and F. So we visit B's left
child 'D' and again D is a root for I and J. So we visit D's left
child 'I' which is the leftmost child. So next we go for visiting D's right
child 'J'. With this we have completed root, left and right parts of node D
and root, left parts of node B. Next visit B's right child 'F'. With this we
have completed root and left parts of node A. So we go for A's right
child 'C' which is a root node for G and H. After visiting C, we go for its
left child 'G' which is a root for node K. So next we visit left of G, but it
does not have left child so we go for G's right child 'K'. With this, we have
completed node C's root and left parts. Next visit C's right child 'H' which
is the rightmost child in the tree. So we stop the process.
A-B-D-I-J-F-C-G-K-H
In Post-Order traversal, the root node is visited after left child and right
child. In this traversal, left child node is visited first, then its right child
and then its root node. This is recursively performed until the right most
node is visited.
I-J-D-F-B-K-G-H-C-A
Threaded Binary Tree is also a binary tree in which all left child pointers
that are NULL (in Linked list representation) points to its in-order
predecessor, and all right child pointers that are NULL (in Linked list
representation) points to its in-order successor.
H-D-I-B-E-A-F-J-C-G
There are two types of heap data structures and they are as follows...
Max Heap
Min Heap
Property #2 (Structural): All levels in a heap must be full except the last level
and all nodes must be filled from left to right strictly.
Max Heap
Max heap data structure is a specialized full binary tree data structure. In a
max heap nodes are arranged based on node value.
Max heap is a specialized full binary tree in which every parent node contains
greater or equal value than its child nodes.
Example
Above tree is satisfying both Ordering property and Structural property
according to the Max Heap data structure.
1. Finding Maximum
2. Insertion
3. Deletion
Finding the node which has maximum value in a max heap is very simple. In a
max heap, the root node has the maximum value than all other nodes. So,
directly we can display root node value as the maximum value in max heap.
Example
Consider the above max heap. Insert a new node with value 85.
Step 1 - Insert the newNode with value 85 as last leaf from left to right.
That means newNode is added as a right child of node with value 75.
After adding max heap is as follows...
Step 2 - Compare newNode value (85) with its Parent node value (75).
That means 85 > 75
Step 3 - Here newNode value (85) is greater than its parent value (75),
then swap both of them. After swapping, max heap is as follows...
Step 4 - Now, again compare newNode value (85) with its parent node
value (89).
Here, newNode value (85) is smaller than its parent node value (89).
So, we stop insertion process. Finally, max heap after insertion of a
new node with value 85 is as follows...
Deletion Operation in Max Heap
In a max heap, deleting the last node is very simple as it does not disturb max
heap properties.
Deleting root node from a max heap is little difficult as it disturbs the max
heap properties. We use the following steps to delete the root node from a
max heap...
Step 1 - Swap the root node with last node in max heap
Step 2 - Delete last node.
Step 3 - Now, compare root value with its left child value.
Step 4 - If root value is smaller than its left child, then compare left
child with its right sibling. Else goto Step 6
Step 5 - If left child value is larger than its right sibling, then swap
root with left child otherwise swap root with its right child.
Step 6 - If root value is larger than its left child, then compare root
value with its right child value.
Step 7 - If root value is smaller than its right child, then swap
root with right child otherwise stop the process.
Step 8 - Repeat the same until root node fixes at its exact position.
Example
Consider the above max heap. Delete root node (90) from the max heap.
Step 1 - Swap the root node (90) with last node 75 in max heap. After
swapping max heap is as follows...
Step 2 - Delete last node. Here the last node is 90. After deleting node
with value 90 from heap, max heap is as follows...
Step 3 - Compare root node (75) with its left child (89).
Here, root value (75) is smaller than its left child value (89). So,
compare left child (89) with its right sibling (70).
Step 4 - Here, left child value (89) is larger than its right sibling (70),
So, swap root (75) with left child (89).
Step 5 - Now, again compare 75 with its left child (36).
Here, node with value 75 is larger than its left child. So, we compare
node 75 with its right child 85.
Step 6 - Here, node with value 75 is smaller than its right child (85). So, we swap both
Step 7 - Now, compare node with value 75 with its left child (15).
Here, node with value 75 is larger than its left child (15) and it does not have right child. So we
a set of links known as edges (or Arcs). Here edges are used to connect the vertices. A graph is
defined as follows...
Graph is a collection of vertices and arcs in which vertices are connected with arcs
Graph is a collection of nodes and edges in which nodes are connected with edges
edges.
Example
Graph Terminology
Vertex
Individual data element of a graph is called as Vertex. Vertex is also known as node. In above
An edge is a connecting link between two vertices. Edge is also known as Arc. An edge is
represented as (startingVertex, endingVertex). For example, in above graph the link between
vertices A and B is represented as (A,B). In above example graph, there are 7 edges (i.e., (A,B),
Undirected Graph
Directed Graph
Mixed Graph
A graph with both undirected and directed edges is said to be mixed graph.
The two vertices joined by edge are called end vertices (or endpoints) of that edge.
Origin
Destination
If a edge is directed, its first endpoint is said to be the origin of it and the other endpoint is said to
Adjacent
If there is an edge between vertices A and B then both A and B are said to be adjacent. In other
words, vertices A and B are said to be adjacent if there is an edge between them.
Incident
Edge is said to be incident on a vertex if the vertex is one of the endpoints of that edge.
Outgoing Edge
Incoming Edge
Degree
Indegree
Total number of incoming edges connected to a vertex is said to be indegree of that vertex.
Outdegree
Total number of outgoing edges connected to a vertex is said to be outdegree of that vertex.
If there are two undirected edges with same end vertices and two directed edges with same
origin and destination, such edges are called parallel edges or multiple edges.
Self-loop
Edge (undirected or directed) is a self-loop if its two endpoints coincide with each other.
Simple Graph
Path
A path is a sequence of alternate vertices and edges that starts at a vertex and ends at other
vertex such that each edge is incident to its predecessor and successor vertex.
Graph Representations
Graph data structure is represented using following representations...
1. Adjacency Matrix
2. Incidence Matrix
3. Adjacency List
Adjacency Matrix
In this representation, the graph is represented using a matrix of size total number of vertices by
a total number of vertices. That means a graph with 4 vertices is represented using a matrix of
size 4X4. In this matrix, both rows and columns represent vertices. This matrix is filled with either
1 or 0. Here, 1 represents that there is an edge from row vertex to column vertex and 0
Incidence Matrix
In this representation, the graph is represented using a matrix of size total number of vertices by
a total number of edges. That means graph with 4 vertices and 6 edges is represented using a
matrix of size 4X6. In this matrix, rows represent vertices and columns represents edges. This
matrix is filled with 0 or 1 or -1. Here, 0 represents that the row edge is not connected to column
vertex, 1 represents that the row edge is connected as the outgoing edge to column vertex and -
1 represents that the row edge is connected as the incoming edge to column vertex.
Adjacency List
In this representation, every vertex of a graph contains list of its adjacent vertices.
For example, consider the following directed graph representation implemented using linked list...
This representation can also be implemented using an array as follows..
Graph Traversal - DFS
Graph traversal is a technique used for a searching vertex in a graph. The graph traversal is also
used to decide the order of vertices is visited in the search process. A graph traversal finds the
edges to be used in the search process without creating loops. That means using graph traversal
we visit all the vertices of the graph without getting into looping path.
There are two graph traversal techniques and they are as follows...
DFS traversal of a graph produces a spanning tree as final result. Spanning Tree is a graph
without loops. We use Stack data structure with maximum size of total number of vertices in the
Step 2 - Select any vertex as starting point for traversal. Visit that vertex and push it on
to the Stack.
Step 3 - Visit any one of the non-visited adjacent vertices of a vertex which is at the top
Step 4 - Repeat step 3 until there is no new vertex to be visited from the vertex which is
Step 5 - When there is no new vertex to visit then use back tracking and pop one vertex
Back tracking is coming back to the vertex from which we reached the current vertex.
Example
Graph Traversal - BFS
Graph traversal is a technique used for searching a vertex in a graph. The graph traversal is also
used to decide the order of vertices is visited in the search process. A graph traversal finds the
edges to be used in the search process without creating loops. That means using graph traversal
we visit all the vertices of the graph without getting into looping path.
There are two graph traversal techniques and they are as follows...
BFS traversal of a graph produces a spanning tree as final result. Spanning Tree is a graph
without loops. We use Queue data structure with maximum size of total number of vertices in
Step 2 - Select any vertex as starting point for traversal. Visit that vertex and insert it
Step 3 - Visit all the non-visited adjacent vertices of the vertex which is at front of the
Step 4 - When there is no new vertex to be visited from the vertex which is at front of the
Step 6 - When queue becomes empty, then produce final spanning tree by removing
Search is a process of finding a value in a list of values. In other words, searching is the process
Linear search algorithm finds a given element in a list of elements with O(n) time complexity
where n is total number of elements in the list. This search process starts comparing search
element with the first element in the list. If both are matched then result is element found
otherwise search element is compared with the next element in the list. Repeat the same until
search element is compared with the last element in the list, if that last element also doesn't
match, then the result is "Element not found in the list". That means, the search element is
Step 2 - Compare the search element with the first element in the list.
Step 3 - If both are matched, then display "Given element is found!!!" and terminate the
function
Step 4 - If both are not matched, then compare search element with the next element in
the list.
Step 5 - Repeat steps 3 and 4 until search element is compared with last element in the
list.
Step 6 - If last element in the list also doesn't match, then display "Element is not
Search is a process of finding a value in a list of values. In other words, searching is the process
Binary search algorithm finds a given element in a list of elements with O(log n) time complexity
where n is total number of elements in the list. The binary search algorithm can be used with only
a sorted list of elements. That means the binary search is used only with a list of elements that
are already arranged in an order. The binary search can not be used for a list of elements
arranged in random order. This search process starts comparing the search element with the
middle element in the list. If both are matched, then the result is "element found". Otherwise, we
check whether the search element is smaller or larger than the middle element in the list. If the
search element is smaller, then we repeat the same process for the left sublist of the middle
element. If the search element is larger, then we repeat the same process for the right sublist of
the middle element. We repeat this process until we find the search element in the list or until we
left with a sublist of only one element. And if that element also doesn't match with the search
Step 3 - Compare the search element with the middle element in the sorted list.
Step 4 - If both are matched, then display "Given element is found!!!" and terminate the
function.
Step 5 - If both are not matched, then check whether the search element is smaller or
Step 7 - If the search element is larger than middle element, repeat steps 2, 3, 4 and 5
Step 8 - Repeat the same process until we find the search element in the list or until
Step 9 - If that element also doesn't match with the search element, then display
Example
the order of nodes basing on their values. In a binary tree, the elements are arranged in the order
they arrive at the tree from top to bottom and left to right.
To enhance the performance of binary tree, we use a special type of binary tree known
as Binary Search Tree. Binary search tree mainly focuses on the search operation in a binary
Binary Search Tree is a binary tree in which every node contains only smaller values in its
In a binary search tree, all the nodes in the left subtree of any node contains smaller values and
all the nodes in the right subtree of any node contains larger values as shown in the following
figure...
Example
The following tree is a Binary Search Tree. In this tree, left subtree of every node contains nodes
with smaller values and right subtree of every node contains larger values.
Every binary search tree is a binary tree but every binary tree need not to be binary search
tree.
1. Search
2. Insertion
3. Deletion
In a binary search tree, the search operation is performed with O(log n) time complexity. The
Step 2 - Compare the search element with the value of root node in the tree.
Step 3 - If both are matched, then display "Given node is found!!!" and terminate the
function
Step 4 - If both are not matched, then check whether search element is smaller or larger
Step 5 - If search element is smaller, then continue the search process in left subtree.
Step 6- If search element is larger, then continue the search process in right subtree.
Step 7 - Repeat the same until we find the exact element or until the search element is
Step 8 - If we reach to the node having the value equal to the search value then display
Step 9 - If we reach to the leaf node and if it is also not matched with the search element,
In a binary search tree, the insertion operation is performed with O(log n) time complexity. In
binary search tree, new node is always inserted as a leaf node. The insertion operation is
performed as follows...
Step 1 - Create a newNode with given value and set its left and right to NULL.
Step 5 - If newNode is smaller than or equal to the node then move to its left child. If
newNode is larger than the node then move to its right child.
Step 6- Repeat the above steps until we reach to the leaf node (i.e., reaches to NULL).
Step 7 - After reaching the leaf node, insert the newNode as left child if the newNode
In a binary search tree, the deletion operation is performed with O(log n) time complexity.
Deleting a node from Binary search tree includes following three cases...
Step 2 - Delete the node using free function (If it is a leaf) and terminate the function.
We use the following steps to delete a node with one child from BST...
Step 2 - If it has only one child then create a link between its parent node and child node.
Step 3 - Delete the node using free function and terminate the function.
We use the following steps to delete a node with two children from BST...
Step 1 - Find the node to be deleted using search operation
Step 2 - If it has two children, then find the largest node in its left subtree (OR)
Step 3 - Swap both deleting node and node which is found in the above step.
Step 4 - Then check whether deleting node came to case 1 or case 2 or else goto step 2
Step 7 - Repeat the same process until the node is deleted from the tree.
Example
10,12,5,4,20,8,7,15 and 13
search tree but it is a balanced tree. A binary tree is said to be balanced if, the difference
between the heights of left and right subtrees of every node in the tree is either -1, 0 or +1. In
other words, a binary tree is said to be balanced if the height of left and right children of every
node differ by either -1, 0 or +1. In an AVL tree, every node maintains an extra information
known as balance factor. The AVL tree was introduced in the year 1962 by G.M. Adelson-
An AVL tree is a balanced binary search tree. In an AVL tree, balance factor of every node
Balance factor of a node is the difference between the heights of the left and right subtrees of
that node. The balance factor of a node is calculated either height of left subtree - height of
right subtree (OR) height of right subtree - height of left subtree. In the following
The above tree is a binary search tree and every node is satisfying balance factor condition. So
Every AVL Tree is a binary search tree but every Binary Search Tree need not be AVL tree.
In AVL tree, after performing operations like insertion and deletion we need to check the balance
factor of every node in the tree. If every node satisfies the balance factor condition then we
conclude the operation otherwise we must make it balanced. Whenever the tree becomes
imbalanced due to any operation we use rotation operations to make the tree balanced.
Rotation is the process of moving nodes either to left or to right to make the tree
balanced.
There are four rotations and they are classified into two types.
In LL Rotation, every node moves one position to left from the current position. To understand LL
In RR Rotation, every node moves one position to right from the current position. To understand
The LR Rotation is a sequence of single left rotation followed by a single right rotation. In LR
Rotation, at first, every node moves one position to the left and one position to right from the
current position. To understand LR Rotation, let us consider the following insertion operation in
AVL Tree...
The RL Rotation is sequence of single right rotation followed by single left rotation. In RL
Rotation, at first every node moves one position to right and one position to left from the current
position. To understand RL Rotation, let us consider the following insertion operation in AVL
Tree...
Operations on an AVL Tree
1. Search
2. Insertion
3. Deletion
In an AVL tree, the search operation is performed with O(log n) time complexity. The search
operation in the AVL tree is similar to the search operation in a Binary search tree. We use the
Step 2 - Compare the search element with the value of root node in the tree.
Step 3 - If both are matched, then display "Given node is found!!!" and terminate the
function
Step 4 - If both are not matched, then check whether search element is smaller or larger
Step 5 - If search element is smaller, then continue the search process in left subtree.
Step 6 - If search element is larger, then continue the search process in right subtree.
Step 7 - Repeat the same until we find the exact element or until the search element is
Step 8 - If we reach to the node having the value equal to the search value, then display
Step 9 - If we reach to the leaf node and if it is also not matched with the search element,
In an AVL tree, the insertion operation is performed with O(log n) time complexity. In AVL Tree,
a new node is always inserted as a leaf node. The insertion operation is performed as follows...
Step 1 - Insert the new element into the tree using Binary Search Tree insertion logic.
Step 3 - If the Balance Factor of every node is 0 or 1 or -1 then go for next operation.
Step 4 - If the Balance Factor of any node is other than 0 or 1 or -1 then that tree is said
to be imbalanced. In this case, perform suitable Rotation to make it balanced and go for
next operation.
The deletion operation in AVL Tree is similar to deletion operation in BST. But after every
deletion operation, we need to check with the Balance Factor condition. If the tree is balanced
after deletion go for next operation otherwise perform suitable rotation to make the tree
Balanced.
Insertion Sort Algorithm
Descending).
Insertion sort algorithm arranges a list of elements in a particular order. In insertion sort
algorithm, every iteration moves an element from unsorted portion to sorted portion until all the
Step 1 - Assume that first element in the list is in sorted portion and all the remaining
Step 2: Take first element from the unsorted portion and insert that element into the
Step 3: Repeat the above process until all the elements from the unsorted portion are
To sort an unsorted list with 'n' number of elements, we need to make (1+2+3+......+n-1) = (n (n-
1))/2 number of comparisions in the worst case. If the list is already sorted then it
Descending). In selection sort, the first element in the list is selected and it is compared
repeatedly with all the remaining elements in the list. If any element is smaller than the selected
element (for Ascending order), then both are swapped so that first position is filled with the
smallest element in the sorted order. Next, we select the element at a second position in the list
and it is compared with all the remaining elements in the list. If any element is smaller than the
selected element, then both are swapped. This procedure is repeated until the entire list is
sorted.
Step 1 - Select the first element of the list (i.e., Element at first position in the list).
Step 2: Compare the selected element with all the other elements in the list.
Step 3: In every comparision, if any element is found smaller than the selected element
Step 4: Repeat the same procedure with element in the next position in the list till the
Example
Complexity of the Selection Sort Algorithm
To sort an unsorted list with 'n' number of elements, we need to make ((n-1)+(n-2)+(n-3)+......+1)
= (n (n-1))/2 number of comparisions in the worst case. If the list is already sorted then it
invented by C. A. R. Hoare.
The quick sort algorithm attempts to separate the list of elements into two parts and then sort
each part recursively. That means it use divide and conquer strategy. In quick sort, the partition
of the list is performed based on the element called pivot. Here pivot element is one of the
The list is divided into two partitions such that "all elements to the left of pivot are smaller
than the pivot and all elements to the right of pivot are greater than or equal to the pivot".
In Quick sort algorithm, partitioning of the list is performed using following steps...
Step 1 - Consider the first element of the list as pivot (i.e., Element at first position in the
list).
Step 2 - Define two variables i and j. Set i and j to first and last elements of the list
respectively.
temp = list[pivot];
list[pivot] = list[j];
list[j] = temp;
quickSort(list,first,j-1);
quickSort(list,j+1,last);
}
}
Example
Complexity of the Quick Sort Algorithm
To sort an unsorted list with 'n' number of elements, we need to make ((n-1)+(n-2)+(n-3)+......+1)
= (n (n-1))/2 number of comparisions in the worst case. If the list is already sorted, then it
algorithm uses one of the tree concepts called Heap Tree. In this sorting algorithm, we use Max
Heap to arrange list of elements in Descending order and Min Heap to arrange list elements in
Ascending order.
The Heap sort algorithm to arrange a list of elements in ascending order is performed using
following steps...
Step 3 - Delete the root element from Min Heap using Heapify method.
Example
Complexity of the Heap Sort Algorithm
To sort an unsorted list with 'n' number of elements, following are the complexities...