OceanofPDF - Com DATA STRUCTURES Through C PROBLEMS AND S - Rashmi V
OceanofPDF - Com DATA STRUCTURES Through C PROBLEMS AND S - Rashmi V
Published by Rashmi
Version 1.0
Copyright © 2020
Author: Rashmi
Preface
The Author is in teaching field for Computer Science and
Engineering colleges. The purpose of writing this book made for
the following.
During teaching when the questions were asked on any topic
of Data Structures, many students used to get confusion to give the
right answer. In order to share the knowledge I have made the
questions and showed the Data Structure implementation examples
through C++ in this book.
The importance of Data Structures is well known in various
engineering fields. The book is structured to cover the key aspects
of the subject on Data Structures. It provides logical method of
explaining various complicated concepts and step wise methods to
explain the topics. Each chapter is well supported with necessary
illustrations, practical examples and solved the problems. This
make the student to understand the subject more clear and makes
more interesting for study. This book will be useful to students as
well as subject learners in graduation and post-graduation in
different universities.
The programs are tested and the same output is written in this
book.
This book will have periodical updates.
Good Luck!
Table of Contents
1. What is an Algorithm?
1.1 What are the properties of algorithm?
1.2 How to write an Algorithm?
1.3 What is Algorithm Analysis and its Complexities?
1.4 What is the Efficiency of Algorithm?
1.5 What is Best Case, Worst Case and Average Case Analysis?
2. What is a Data Structure?
2.1 What are the Types of Data Structures?
2.1.1 What are Primitive Data Structures?
2.1.2 What are Non-Primitive Data Structures?
2.2 What are the Operations Performed on Data Structures?
3. What is an Array?
3.1 What are the Operations Performed on Arrays?
4. What is Stack ADT?
4.1 What are the Operations Performed on the Stack?
4.1.1 What is the Algorithm for Push Operation on Stacks?
4.1.2 What is the Algorithm for Pop Operation on Stacks?
4.2 What are the Applications Performed on Stack?
4.3 How to Implement Stack Using Arrays?
5. What is Queue ADT?
5.1 What are the Operation Performed on Queue?
5.1.1 What is the Algorithm for Enqueue Operation on Queue?
5.1.2 What is the Algorithm for Dequeue Operation on Queue?
5.2 What are the Applications of Queues?
5.3 How to Implement Queue Using Arrays?
6. How to Evaluate the Expressions?
6.1 How to Evaluation of Postfix Expression?
6.2 How to Convert Infix to Postfix Expressions?
7. What are Linked Lists?
7.1 What are Single Linked Lists and Chains?
7.1.1 What are the basic operation performed on single linked list?
7.1.2 How to Deletion of a Node in Singly Linked List?
7.1.3 How to Traverse and Display a Singly Linked List?
7.2 What are Circular Lists?
7.2.1 How to Implement Circular Linked List?
7.2.2 How to perform basic operation performed on Single Linked
List?
7.3 What are Linked Stacks?
7.3.1 How to implement Push operation on Linked Stacks?
7.3.2 How to implement Pop operation on Linked Stacks?
7.4 What are Linked Queues?
7.4.1 How to implement Enqueue operation on Linked Queues?
7.4.2 How to implement Dequeue operation on Linked Queues?
7.5 What is a Polynomial?
7.5.1 How to Represent the Polynomials using Linked Lists?
7.5.2 What is Polynomial Addition?
7.5.3 What is Circular Representation of Polynomials?
7.6 What are Equivalence Classes?
7.7 What is a Sparse Matrix?
7.7.1 How to represent Sparse Matrix?
7.8 What are Doubly Linked Lists?
7.8.1 What are the basic operation performed on Doubly Linked
List?
7.9 What are Generalized Lists?
7.10 What are Recursive Algorithms for Lists?
7.10.1 What are Reference Count, Shared and Recursive Lists?
8. What are Trees?
8.1 What is the Terminology of Tree Data Structure?
8.2 What are the Representation of Trees?
8.3 What are Binary Trees?
8.2.1 What are the Properties of Binary Trees?
8.2.2 What are the Types of Binary Trees?
8.2.3 How to Represent the Binary Trees?
8.2.4 What are Binary Tree Traversals?
8.4 What are Expression Trees?
8.5 What are Threaded Binary Trees?
8.5.1 What are Threads?
8.5.2 What is Inorder Traversal of a Threaded Binary Tree?
8.5.3 How to Insert a node into a Threaded Binary Tree?
8.6 What are Heaps?
8.6.1 What are Priority Queues?
8.6.2 What are different types of Heaps?
8.7 What are Binary Search Trees?
8.7.1 What is the search operation in Binary Search Tree?
8.7.2 How to insert into a Binary Search Tree?
8.7.3 How to delete from Binary Search Tree?
8.7.4 How to Join two Binary Search Trees?
8.7.5 How to Split Binary Search Trees?
8.7.6 How to find the Height of Binary Search Tree?
9. What is a Graph?
9.1 What is the Graph Abstract Data Type?
9.2 What are the different Types of Graphs?
9.3 What are the Properties of Graph?
9.4 How to Represent a Graph?
9.4.1 What is Adjacency Matrix Representation of Graphs?
9.4.2 What is Adjacency List Representation of Graphs?
9.4.3 What is Adjacency Multilist Representation of Graphs?
9.5 What are Elementary Graph Operations?
9.5.1 What is Breadth First Search?
9.5.2 What is Depth First Search?
9.6 What are Connected Components?
9.7 What are Spanning Trees?
9.8 What are Biconnected Components?
9.9 What is Minimum Cost Spanning Trees?
9.9.1 What is Kruskal’s Algorithm?
9.9.2 What is Prim’s Algorithm?
9.9.3 What is Sollins Algorithm?
9.10 What is the Shortest Path and Transitive Closure?
9.11 What is Single Source/All Destinations by Dijkstra’s Algorithm?
9.12 What is All Pairs Shortest Path?
10. What is Sorting?
10.1 What is Insertion Sort?
10.2 What is Quick Sort?
10.3 What is Merge Sort?
10.4 What is Heap Sort?
10.5 What is Radix Sort?
10.6 What is Selection Sort?
10.7 What is Bubble Sort?
Laboratory Work on Data Structures
Experiment 1: How to implement Multistack in a Single Array through C++
Experiment 2: How to implement Circular Queue through C++
Experiment 3: How to implement Singly Linked List through C++
Experiment 4: How to implement Doubly Linked List through C++
Experiment 5: How to implement Binary Search Tree through C++
Experiment 6: How to implement Heaps through C++
Experiment 7: How to implement Breadth First Search Techniques.
Experiment 8: How to implement Depth First Search Technique through
C++
Experiment 9: How to implement Prim’s Algorithm through C++
Experiment 10: How to implement Dijkstra’s Algorithm through C++
Experiment 11: How to implement Kruskal’s Algorithm through C++
Experiment 12: How to implement Merge Sort though C++
Experiment 13: How to implement Quick Sort through C++
Experiment 14: How to implement Data Searching using Divide and
Conquer Technique through C++
1. What is an Algorithm?
Definition of Algorithm: The algorithm is defined as a collection of
unambiguous instructions occurring in some specific sequence and such an
algorithm should produce output for given set of input in finite amount of
time.
After understanding the problem statement we have to create an
algorithm for the given problem. The algorithm is then converted into some
programming language and then given to some computing device. The
computer then executes this algorithm which is actually submitted in the
form of some source program. During the process of execution it requires
some set of input. With the help of algorithm (in the form of program) and
input set, the result is produced as the output. If the given input is invalid
then it should raise appropriate error message otherwise correct input will
be produced as the output.
11.
The conditional statements such as if-then or if-then-else are
written in the following form:
if (condition) then statement
if (condition) then statement else statement
If the if-then statement is of compound statement then { and }
should be used for enclosing block.
12.
while statement can be written as:
while (condition) do
{
Statement 1;
Statement 2;
...
Statement n;
}
When the condition is true the block enclosed with { } gets executed
otherwise statement after } will be executed.
13.
The general form for writing for loop is:
for variable ← value 1 to value n do
{
Statement 1;
Statement 2;
...
Statement n;
}
Here, value1 is initialization condition and valuen is a terminating
condition. The step indicates increments or decrements of value1 for
executing for loop. Sometimes the keyword step is used to denote
increment or decrement the value of the variable for example:
for i←1 to n step 1
{
write(i);
}
14.
The break statement is used to exit the inner loop. The return
statement is used to return control from one point to another.
Generally used while existing from function.
The statements in an algorithm executes in sequential order i.e., in
the same order as they appear one after the other.
Example 1: Write an algorithm to check weather given number is even or
odd.
Algorithm eventest(val)
//Problem Description: This algorithm test weather given
//number is even or odd
//Input: The number to be tested i.e., val
//Output: Appropriate messages indicating to be even or oddness
if(val%2==0) then
write (“Given number is even”)
else
write(“Given number is odd”)
Example2: Write an algorithm to find factorial of n number.
Algorithm fact(n)
//Problem Description: This algorithm finds the factorial.
//of given number n
//Input: The number n of which the factorial is to be calculated.
//Output: Factorial value of given n number
if(n←1) then
return 1;
else
return n*fact(n-1);
1.3 What is Algorithm Analysis and its Complexities?
The analysis of the program does not mean simply working of the
program but to check weather for all possible situations program works or
not. The analysis also works for efficiency of program. Efficiency in the
sense:
We have shown the number of times the above code gets executed.
Hence we can say the total frequency count of the above code is:
1+6+5+5=17
Now let us consider the execution of for loop.
1.5 What is Best Case, Worst Case and Average Case Analysis?
If an algorithm takes minimum amount of time to run to completion for
a specific set of input then it is called as best case time complexity.
For example: While searching a particular element by using sequential
search we get the desired element at first place itself then it is called best
case time complexity.
If an algorithm takes maximum amount of time to run to completion
for a specific set of input then it is called as worst case time complexity.
For example: While searching a particular element by using linear
search method we get the desired element at end of the list then it is called
worst case time complexity.
The time complexity that we get for certain set of inputs is in an
average same. Then for corresponding input such a time complexity is
called as an average case time complexity.
2. What is a Data Structure?
Data structure: A data structure is the mathematical or logical way of
organizing the data elements in the memory of a computer so that it can be
used efficiently.
or
Organization of data in memory locations for convenient handling of user is
called as Data Structure.
Example: Array, stack, queue, tree, graph.
2.1 What are the Types of Data Structures?
Data structures are generally categorized into two classes:
1) Primitive data structures.
2) Non-primitive data structures.
Limitations of arrays:
Here we will start from beginning and will go till last element and
during this process we will access value of each element exactly once as
below:
A [1] = 100
A [2] = 200
A [3] = 300
A [4] = 400
A [5] = 500
2) Insertion: It is used to add a new data item in the given collection of
data items.
Example for insertion of element into an array:
We have linear array A has the following elements as shown below:
11, 21, 51, 31, 15
i. linear search
ii. Binary search.
1. Find the middle element of the array (i.e., n/2 is the middle
element if the array or the sub-array contains n elements).
2. Compare the middle element with the data to be searched, and
then there are following three cases.
a) If it is a desired element, then search is successful.
b) If it is less than desired data, then search only the first half of
the array, i.e., the elements which come to the left side of the
middle element.
c) If it is greater than the desired data, then search only the
second half of the array, i.e., the elements which come to the
right side of the middle element.
d) Repeat the same steps until an element are found or exhaust the
search area.
Example 1 for Binary Search:
In the given list of elements 11, 13, 21, 33, 51, 56, 66, 81, 99 find the
location of search element 13.
Step 1: Internally in the memory the above elements are stored as shown
below.
Step 3: The search element 13 is compared with the middle element 13.
(Since, middle element= (0+3)/2 = 1)
Both the middle elements and the element to search are same i.e., 13
which is present at the index 1.
Example 2 for Binary Search:
In the given list of elements 11, 13, 21, 33, 51, 56, 66, 81, 99 find the
location of search element 81.
Step 1: Internally in the memory the above elements are stored as shown
below.
Since both are not matching and search element 81 is greater than 51. So,
we search only in the right sublist (i.e., 56, 66, 81, 99). (Since, middle
element= (0+8)/2 = 4)
Step 3: The search element 80 is compared with the middle element 66.
(Since, middle element= (5+8)/2 = 6)
Since both are not matching and 81 is larger than 66, we search only the
right sublist (i.e., 81 and 99). (Since, middle element= (6+8)/2 = 7)
Finally, search element and the element present are equal i.e. 81 which is
present at the index 7.
Algorithm for Binary Search:
Algorithm Binsearch (a,low,high,key)
{
// low:=0; high:=n;
If(low==high) then
{
If(key=a[mid]) then return low
else return 0;
}
else
{
//reduce p into smaller problem
mid:=[(low+high)/2];
if(key==a[mid]) then return mid
else if (x<a[mid]) then
return Binsearch(a,low,mid-1,key);
else return Binsearch(a,mid+1,high,key);
}
}
PROGRAM for Binary Search with Recursion:
//Implementation of Binary Search without using recursion
#include<stdio.h>
#include<conio.h>
int main()
{
int i,S,a[100],n,flag=0,st,end,mid;
printf("\nEnter the no of elements in the list: ");
scanf("%d",&n);
printf("\nEnter the sorted list: ");
for(i=0;i<n;i++)
{
printf("\nEnter a[%d] element : ",i);
scanf("%d",&a[i]);
}
printf("\nEnter element to be searched: ");
scanf("%d",&S);
st=0,end=n-1;
while(st<=end)
{
mid=(st+end)/2;
if(S==a[mid])
{
flag=1;
printf("\n%d found at %d location:",S,mid+1);
break;
}
else if(S>a[mid])
st=mid+1;
else
end=mid-1;
}
if(flag==0)
printf("\n %d Not Found: ",S);
return 0;
}
PROGRAM for Binary Search using Recursion:
//Implementation of Binary Search using recursion
#include<stdio.h>
#include<conio.h>
#define MAX 20
int a[MAX],n;
void bubble()
{
int t,i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n-1-i;j++)
{
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
}
int binary(int l,int u, int key)
{
int mid;
if(l<=u)
{
mid=(l+u)/2;
if(key==a[mid])
return mid;
else if(key>a[mid])
return binary(mid+1,u,key);
else
return binary(l,mid-1,key);
}
return -1;
}
void main()
{
int i,key,pos;
clrscr();
printf("\nEnter the no of elements to sort: ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\nEnter a[%d] element : ",i);
scanf("%d",&a[i]);
}
bubble();
printf("\nAfter rearange the element in order: \n");
for(i=0;i<n;i++)
printf(" %d",a[i]);
printf("\nEnter element for search: ");
scanf("%d",&key);
pos=binary(0,n-1,key);
if(pos!=-1)
printf("\n%d found at %d location:",key,++pos);
else
printf("\n %d Not Found: ",key);
getch();
}
Complexity of Binary Search Algorithm:
Best case: Best case of linear search occurs when search element is equal to
the middle element of the array. In this case, only one comparison will be
made so best case time complexity is O(1).
Worst case: In this case maximum logn comparisons are required. So its
time complexity is O(logn).
Average case: Time complexity is O(logn).
5) Sorting:
Sorting means arranging the elements of an array either in
ascending order or in descending order. That is, if A is an array, then the
elements of A are arranged in a sorted order (ascending order) in such a
way that A[0] < A[1] < A[2] < …..<A[N].
Example int A[] = {21, 34, 11, 9, 1, 0, 22};
Then the sorted array (ascending order) can be given as: A[] = {0,
1, 9, 11, 21, 22, 34};
Different techniques for sorting are:
i. Selection Sort
ii. Bubble Sort
iii. Insertion Sort
iv. Quick Sort
v. Merge Sort
vi. Radix Sort
All the sorting techniques will be discussed in the last chapter.
4. What is Stack ADT?
STACK AS ABSTRACT DATATYPE (ADT):
A stack is a data structure in which addition of new element or
deletion of an existing element always takes place at the same end. This end
is known as top of stack. When an item is added to a stack, the operation is
called push, and when an item is removed from the stack the operation is
called pop. Stack is also called as Last-In-First-Out (LIFO) list. It means
that the last element that is inserted will be the first element to be removed
from the stack.
Step 2: Now, insert 11 to the queue. Then queue status will be:
Step 3: Next, insert 22 to the queue. Then the queue status is:
Step 4: Again insert another element 33 to the queue. The status of the
queue is:
Step 5: Again insert another element 44 to the queue. The status of the
queue is:
Step 6: Again insert another element 55 to the queue. The status of the
queue is:
Step 7: Again insert another element 66 to the queue. The status of the
queue is:
An element can be added to the queue only at the rear end of the queue.
Before adding an element in the queue, it is checked whether queue is full.
If the queue is full, then addition cannot take place. Otherwise, the element
is added to the end of the list at the rear side.
5.1.2 What is the Algorithm for Dequeue Operation on Queue?
Algorithm for Dequeue operation (deleting an element):
Step 2: Now, delete an element 11. The element deleted is the element at the
front of the queue. So the status of the queue is:
Step 3: Now, delete an element 22. The element deleted is the element at the
front of the queue. So the status of the queue is:
Step 4: Now, delete an element 33. The element deleted is the element at the
front of the queue. So the status of the queue is:
Step 5: Now, delete an element 44. The element deleted is the element at the
front of the queue. So the status of the queue is:
Step 6: Now, delete an element 55. The element deleted is the element at the
front of the queue. So the status of the queue is:
The dequeue operation deletes the element from the front of the queue.
Before deleting and element, it is checked if the queue is empty. If not the
element pointed by front is deleted from the queue and front is now made to
point to the next element in the queue.
5.2 What are the Applications of Queues?
Queue is used when have to be processed in First In First Out order like
Breadth First Search. This property of Queue makes it also useful in
following kind of scenarios.
1) When a resource is shared among multiple consumers.
Examples include CPU scheduling, Disk Scheduling.
2) When data is transferred asynchronously (data not necessarily
received at same rate as sent) between two processes.
Examples include IO Buffers, pipes, file IO, etc.
5.3 How to Implement Queue Using Arrays?
Implementation of Queues using Arrays:
The stacks can be implemented by using arrays and linked lists. If
arrays are used for implementing the queues, it would be very easy to
manage the queues. But the problem with an array is that we are required to
declare the size of the array before using it in a program. This means the
size of the queue should be fixed.
C++ program to illustrate about queues using arrays:
#include<iostream.h>
#include<conio.h>
class queue
{
int que[5];
int front, rear;
public:
queue()
{
front = rear = -1;
}
void enqueue(int x)
{
if(rear > 4)
{
cout<<”queue overflow”;
front = rear = -1;
return;
}
que[++rear]=x;
cout<<”inserted”<<x;
}
void dequeue()
{
it(front = rear)
{
cout<<”queue empty”;
return;
}
cout<<”deleted”<<que[front++];
}
void display()
{
it(rear = front)
{
cout<<”queue empty”;
return;
}
for(int i=front + 1; i<=rear; i++)
cout<<que[i]<<” “;
}
};
main()
{
int opt, ele;
queue qt;
while(1)
{
cout<<”\n 1. enqueue 2. dequeue 3. display 4. exit”; cout<<” enter the
option”;
cin>>opt;
switch(opt)
{
case 1:
cout<<” enter the element”;
cin>>ele;
qt.enqueue(ele);
break;
case 2:
qt.dequeue();
break;
case 3:
qt.display();
break;
default: exit(0);
}
}
}
6. How to Evaluate the Expressions?
EVALUATION OF EXPRESSIONS:
Expression:
“An expression is defined as the combination of operators and operands”.
“An expression is defined as the combination of variables, constants and
operators arranged as per the syntax of the language”.
Operand is the quantity on which a mathematical operation is performed.
Operand may be a variable like x, y, z or a constant like 5, 4, 6 etc. Operator is a
symbol which performs a mathematical or logical operation between the operands.
Examples of operators include +, -, *, /, ^ etc.
An expression can be represented using three different notations.
They are infix, postfix and prefix notations:
Infix: An arithmetic expression in which we fix (place) the arithmetic operator in
between the two operands.
Example: (A + B) * (C - D)
Prefix: An arithmetic expression in which we fix (place) the arithmetic operator
before (pre) its two operands. The prefix notation is called as polish notation.
Example: * + A B – C D
Postfix: An arithmetic expression in which we fix (place) the arithmetic operator
after (post) its two operands. The postfix notation is called as suffix notation and is
also referred to reverse polish notation.
Example: A B + C D - *
The three important features of postfix expression are:
1) The operands maintain the same order as in the equivalent infix expression.
2) The parentheses are not needed to designate the expression unambiguously.
3) While evaluating the postfix expression the priority of the operators is no
longer relevant.
We consider five binary operations: +, -, *, / and $ or ↑ (exponentiation). For
these binary operations, the following in the order of precedence (highest to lowest):
Operator Precedence Value
exponentiation ($, ^) highest 1
*, / next highest 2
+, - lowest 3
As programmers we write the expressions into two types. They are simple
and complex expressions. Let us consider the complex expression as follows:
x=a/b–c+d*e–a*c
Description Operator Rank Associatively
Function expression ()
1 Left to Right
Array expression []
Unary plus +
Unary minus -
Increment/Decrement ++/--
Logical negation !
One’s complement ~ 2 Right to left
Pointer reference *
Address of &
Size of an object Sizeof
Type cast (conversion) (type)
Multiplication *
Division / 3 Left to Right
Modulus %
Addition +
4 Left to Right
Subtraction -
Left shift <<
5 Left to Right
Right shift >>
Less than <
Less than or equal to <=
6
Greater than >
Left to Right
Greater than or equal to >=
Equality ==
7 Left to Right
Not equal to !=
Bit wise AND & 8 Left to Right
Bit wise XOR ^ 9 Left to Right
Bit wise OR | 10 Left to Right
Logical AND && 11 Left to Right
Logical OR || 12 Left to Right
Conditional ?: 13 Right to Left
Assignment =,*=,/=,%=,+=, 14 Right to Left
-, =,& etc
Comma operator , 15 Left to Right
In the above expression we first understand the meaning of the expression and
then the order of performing the operation. For example, a = 4, b = c = 2, d = e = 3
then the value of x is found as ((4 / 2) – 2) + (3 * 3) – (4 * 2)
=0 + 9 – 8
=1
Or
(4 / (2 – 2 + 3)) * (3 – 4) * 2
= (4 / 3) * (- 1) * 2
= - 2.66666
Mostly we prefer the first method because we know multiplication is performed
before addition and division is performed before subtraction. In any programming
language, we follow hierarchy of operators for evaluation of expressions. The
operator precedence is shown in the above table.
6.1 How to Evaluation of Postfix Expression?
EVALUATION OF POSTFIX EXPRESSION:
The standard representation for writing expressions is infix notation which
means that placing the operator in between the operands. But the compiler uses the
postfix notation for evaluating the expression rather than the infix notation.
It is an easy task for evaluating the postfix expression than infix expression
because there are no parentheses. To evaluate an expression we scan it from left to
right. The postfix expression is evaluated easily by the use of a stack.
When an operand is seen, it is pushed onto the stack. When an operator is seen,
the operator is applied to the two operands that are popped from the stack and the
result is pushed onto the stack. When an expression is given in postfix notation,
there is no need to know any precedence rules.
Example 1:
Evaluate the postfix expression: 6 2 / 3 - 4 2 * +
Stack
Token Top
[0] [1] [2]
6 6 0
2 6 2 1
/ 06-Feb 0
3 06-Feb 3 1
- 6/2–3 0
4 6/2–3 4 1
2 6/2–3 4 2 2
* 6/2–3 4*2 1
+ 6/2–3+4*2 0
Creating a structure with one data item and a next pointer, which
will be pointing to next node of the list. This is called as self-
referential structure.
Initialize the start pointer to be NULL.
struct slinklist
{
int data;
struct slinklist *next;
};
typedef struct slinklist node;
node start=NULL;
7.1.1 What are the basic operation performed on single linked list?
The different operations performed on the single linked list are listed
as follows.
1) Creation
2) Insertion
3) Deletion
4) Traversing & Display
7.1.1.1 How to creating a node for Single Linked List?
Creating a singly linked list starts with creating a node. Sufficient
memory has to be allocated for creating a node. The information is stored in
the memory, allocated by using the new() function. The function getnode(),
is used for creating a node, after allocating memory for the node, the
information for the node data part has to be read from the user and set next
field to NULL and finally return the node.
node* getnode()
{
node* newnode;
newnode = new node;
cout<<“Enter data”;
cin>>newnode->data;
newnode-data=NULL;
return newnode;
}
i. The next field of the new node is made to point the first
node (i.e. start node) in the list by assigning the address of
the first node.
ii. The start pointer is made to point the new node by
assigning the address of the new node.
void insert_at_beg()
{
node *newnode;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
newnode -> next = start;
start = newnode;
}
}
7.1.1.4 How to insert a node at the ending of the Singly Linked List?
The following steps are followed to insert a new node at the end of the
list:
1.
Get the new node using getnode() then newnode = getnode();
2.
If the list is empty then start = newnode.
3.
If the list is not empty follow the steps given below:
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
Fig. 7.4: Insertion of node at the ending of the Singly Linked List
The function insert_at_end(), is used for inserting a node at the end.
void insert_at_end()
{
node *newnode, *temp;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
7.1.1.5 How to insert a node at the specified position in the Singly
Linked List?
The following steps are followed, to insert a new node in an
intermediate position in the list:
newnode = getnode();
Fig. 7.5: Insertion of node at the specified position in Singly Linked List
The function insert_at_mid(), is used for inserting a node in the
intermediate position.
void insert_at_mid()
{
node *newnode, *temp, *prev;
int pos, nodectr, ctr = 1;
newnode = getnode();
cout<< Enter the position;
cin>>pos;
nodectr = countnode(start);
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr++;
}
prev -> next = newnode;
newnode -> next = temp;
}
else
{
cout<< pos;
}
}
7.1.2 How to Deletion of a Node in Singly Linked List?
Another operation that can be done in a singly linked list is the
deletion of a node. Memory is to be released for the node to be deleted. A
node can be deleted from the list from three different places.
1) Deleting a node at the beginning.
2) Deleting a node at the end.
3) Deleting a node at specified position.
7.1.2.1 How to delete a node at the beginning of the Singly Linked List?
The following steps are followed, to delete a node at the beginning
of the list:
The function delete_at_beg(), is used for deleting the first node in the list.
void delete_at_beg()
{
node *temp;
if(start == NULL)
{
cout<< No nodes are exist;
return ;
}
else
{
temp = start;
start = temp -> next;
delete temp;
cout<<Node deleted;
}
}
7.1.2.2 How to delete a node at the end of the Singly Linked List?
The following steps are followed to delete a node at the end of the list:
1.
If list is empty then display “Empty List‟ message
2.
If the list is not empty, follow the steps given below.
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
ctr = 1;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr++;
}
prev -> next = temp -> next;
delete temp;
cout<<node deleted;
}
Fig. 7.8: Deletion of node at the specified position node in the Singly Linked List
The function delete_at_mid(), is used for deleting the specified position
node in the list.
void delete_at_mid()
{
int ctr = 1, pos, nodectr;
node *temp, *prev;
if(start == NULL)
{
cout<<Empty List;
return ;
}
else
{
cout<<Enter position of node to delete;
cin>>pos;
nodectr = countnode(start);
if(pos > nodectr)
{
cout<<This node doesnot exist;
}
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr ++;
}
prev -> next = temp -> next;
delete temp;
cout<<Node deleted;
}
else
{
cout<<Invalid position;
getch();
}
}
}
7.1.3 How to Traverse and Display a Singly Linked List?
Traversal and Displaying a Singly Linked List (Left to Right):
To display the information, you have to traverse (move) a linked list,
node by node from the first node, until the end of the list is reached.
Traversing a list involves the following steps.
1.
Assign the address of start pointer to a temp pointer.
2.
Display the information from the data field of each node.
The function traverse() is used for traversing and displaying the
information stored in the list from left to right.
void traverse()
{
node *temp;
temp = start;
cout<< The contents of List (Left to Right); if(start == NULL )
cout<<Empty List;
else
{
while (temp != NULL)
{
cout<<temp -> data;
temp = temp -> next;
}
}
cout<<X;
}
7.2 What are Circular Lists?
Circular linked list is a linked list which consists of collection of
nodes each of which has two parts, namely the data part and the next part.
The data part holds the value of the element and the next part has the
address of the next node. The last node of list has the next pointing to the
first node thus making the circular traversal possible in the list.
It is just a single linked list in which the next field of the last node
points back to the address of the first node. A circular linked list has no
beginning and no end. In circular linked list no null pointers are used, hence
all pointers contain valid address.
Fig.7.9: Circular Linked List
AbstractDataType CLinkedList
{
Instances:
finite collection of zero or more elements linked by pointers
Operations:
Count( ): Count the number of elements in the list.
Addatbeg(x): Add x to the beginning of the list.
Addatend(x): Add x at the end of the list.
Insert(k, x): Insert x just after kth element.
Delete(k): Delete the kth element.
Search(x): Return the position of x in the list otherwise return -1 if not
found
Display( ): Display all elements of the list
}
7.2.1 How to Implement Circular Linked List ?
Before writing the code to build the list, we need to create a start
node, used to create and access other nodes in the linked list.
Creating a structure with one data item and a next pointer, which
will be pointing to next node of the list. This is called as self-
referential structure.
Initialize the start pointer to be NULL.
struct clinklist
{
int data;
struct clinklist* next;
};
typedef struct clinklist node; node *start = NULL;
1. Creation
2. Insertion
3. Deletion
4. Traversing
5. Display
node* getnode()
{
node* newnode;
newnode = new node;
cout<< Enter data;
cin>>newnode -> data
newnode -> next = NULL;
return newnode;
}
Creating a Circular Linked List with “n” number of nodes:
The following steps are to be followed to create “n” number of nodes.
1.
Get the new node using getnode().
newnode = getnode();
2.
If the list is empty, assign new node as start.
start = newnode;
newnode -> next = start;
3. If the list is not empty, follow the steps given below: last = start;
while(last -> next != start)
last = last -> next;
newnode -> next = start;
start = newnode;
last -> next = start;
7.2.2.2.2 How to insert a node at the end of the list in Circular List?
The following steps are followed to insert a new node at the end of the
list:
1. Enqueue operation
2. Dequeue operation
7.4.1 How to implement Enqueue operation on Linked Queues?
In linked list representation of queue, the addition of new element to
the queue takes place at the rear end. It is the normal operation of adding a
node at the end of a list.
Algorithm for Enqueue (inserting an element):
if front = NULL then
rear = front = temp;
return
end if
rear - > next = temp;
rear = rear - > next;
7.4.2 How to implement Dequeue operation on Linked Queues?
The dequeue( ) operation deletes the first element from the front end
of the queue. Initially it is checked, if the queue is empty. If it is not empty,
then return the value in the node pointed by front, and moves the front
pointer to the next node.
Algorithm for Dequeue (deleting an element)
if front = NULL;
display “Queue is empty”;
return
else
while front != NULL;
temp = front;
front = front - > next;
delete temp;
end while
end if
7.5 What is a Polynomial?
A polynomial is of the form
Where, ci is the coefficient of the ith term and n is the degree of the
polynomial. Some examples are:
1) 5x2 + 3x + 1
2) 12x3 + 4
3) 4x6 + 10x4 – 5x + 3
4) 5x4 – 8x3 + 2x2 + 4x1 + 9
5) 23x9 + 18x7 – 41x6 + 163x4 – 5x + 3
Polynomial as Abstract Data Type:
The abstract data type of a polynomial is defined as follows:
class polynomial
{
instances:
p(x) = a0 x0 + a1 x1 + ……….. + an xn , is a set of ordered pairs
Fig. 7.17: Singly Linked List for the Polynomial F(x) = 5x4 – 8x3 + 2x 2 + 4x1 + 9
Save space
Easy to maintain
Do not need to allocate memory size initially
Disadvantages for Polynomials using Linked Lists:
Fig. 7.18: Circular Linked List for the Polynomial F(x) = 5x4 – 8x3 + 2x2 + 4x1 + 9
void equivalence()
{
initialize seq to null and out to true;
while(there are more pairs)
{
read the next pair (i,j);
put j on the seq(i) list;
put i on the seq(j) list;
}
for(i= 0; i<n; i++)
if(out(i))
{
out(i) = false;
output this equivalence class;
}
}
2. row node
3. column node
The matrix representation for the sparse matrix is shown below for
example.
AbstractDataType DLinkedList
{
instances:
finite collection of zero or more elements linked by two pointers, one
pointing the previous node and the other pointing to the next node.
operations:
Count(): Count the number of elements in the list.
Addatbeg(x): Add x to the beginning of the list.
Addatend(x): Add x at the end of the list.
Insert(k, x): Insert x just after kth element.
Delete(k): Delete the kth element.
Search(x): Return the position of x in the list otherwise return -1 if not
found
Display( ): Display all elements of the list
}
Implementation of Doubly Linked List:
Before writing the code to build the list, we need to create a start
node, used to create and access other nodes in the linked list.
7.8.1 What are the basic operation performed on Doubly Linked List?
The different operations performed on the doubly linked list are
listed as follows.
1. Creation
2. Insertion
3. Deletion
4. Traversal and Display
Creating a node for Doubly Linked List:
Creating a doubly linked list starts with creating a node. Sufficient
memory has to be allocated for creating a node. The information is stored in
the memory, allocated by using the new() function.
The function getnode(), is used for creating a node, after allocating
memory for the node, the information for the node data part has to be read
from the user and set left and right field to NULL and finally return the
node.
node* getnode()
{
node* newnode;
newnode = new node;
cout<< Enter data;
cin>>newnode -> data;
newnode -> left = NULL;
newnode -> right = NULL;
return newnode;
}
7.8.1.1 How to Create a Doubly Linked List?
The following steps are to be followed to create “n‟ number of nodes.
1) Get the new node using getnode(). newnode = getnode();
2) If the list is empty, assign new node as start. start = newnode;
3) If the list is not empty, follow the steps given below.
i. The left field of the new node is made to point the previous
node.
ii. The previous nodes right field must be assigned with
address of the new node.
4) Repeat the above steps “n” times.
Fig. 7.27: Insertion of node at the beginning of the Doubly Linked List
Fig. 7.28: Insertion of node at the ending of the Doubly Linked List
Fig. 7.31: Deletion of the node at the ending of the Doubly Linked List
Fig. 7.32: Deletion of the node at the specified position of the Doubly Linked List
p(x,y,z) = x 10 y 3 z 2 + 2x 8 y 3 z 2 + 3x 8 y 2 z 2 + x 4 y 4 z + 6x 3 y 4 z + 2yz
A sequential representation for p using the structure with four fields
to represent a single array element. The node is of the form
The node vary in size and difficult to maintain storage. Then the
idea is to use a general list structure with nodes of fixed size and rewrite the
p(x,y,z) as
((x 10 + 2x 8 )y 3 + 3x 8 y 2 )z 2 + ((x 4 + 6x 3 )y 4 + 2y)z
Every polynomial can be represented using node of type polynode and is
defined as follows:
enum triple {var, ptr, no};
class polynode
{
polynode *link
int exp;
triple trio;
union{
char var1;
polynode *dlink;
int coef;
};
};
In this representation, there three types of nodes depending on the
value of trio. If trio == var, then the node is head node, the field var1 is used
to indicate the name of the variable and exp = 0. If trio == ptr, then
coefficient itself is a list pointed by the dlink field. If trio == no, then
coefficient is an integer and is stored in the coef field and exp is based on
the list. The representation for the polynomial p=3x2 y is as follows:
Fig. 7.35: Generalized Lists for Reference Counts, Shared and Recursive Lists
The values in the data field of the head node is the reference count
of the corresponding list. When the lists are shared by other lists we need a
mechanism to determine whether or not the list of nodes may be physically
returned to available space list. This mechanism provides reference count
maintained in the head node of each list. Since the data field of the head
node is free the reference count is maintained in this field. The reference
count is the number of pointers to that list.
1.
ref(x) = 1, accessible only via x.
2.
ref(y) = 3, pointed to by y and two pointers from z
3.
ref(z) = 1, accessible only via z
4.
ref(w) = 2, accessible via w and a pointer to itself.
When reference count decreases and becomes zero then all the
nodes are physically returned to the available space list. the class definition
for genlist is unchanged and genlistnode is as follows:
2) Edge:
3) Parent:
4) Child:
5) Siblings:
6) Leaf:
The nodes which does not have child are called as leaf node.
Nodes that have degree zero are called leaf or terminal nodes.
Leaf nodes are also known as external nodes or terminal nodes.
For example, in the below tree the nodes D, I, F, G, H are the leaf nodes.
7) Internal nodes:
Nodes which have at least one child are called as internal nodes.
Nodes other than leaf nodes are internal nodes.
These nodes are also called as non-terminal nodes.
For example, the below tree A, B, C , E are internal nodes or non-
terminal nodes.
8) Degree:
10) Height:
11) Depth:
When arrays are used to represent the binary trees, then an array of
k
size 2 is declared where, k is the depth of the tree. For example if the
3
depth of the binary tree is 3, then maximum 2 - 1 = 7 elements will be
present in the node and hence the array size will be 8. This is because the
elements are stored from position one leaving the position 0 vacant.
For skewed binary tree of depth ‘k’, will require 2k -1 space where we
will use only k spaces. The below figure shows how the skewed binary tree
represented in the array.
Fig. 8.15: Array Representation of Skewed Binary Tree
In the preorder traversal, the node element is visited first and then
the left subtree of the node and then the right subtree of the node is visited.
Consider we have 6 nodes in the tree A, B, C, D, E, F. The traversal always
starts from the root of the tree. The node A is the root and hence it is visited
first. The value at this node is processed.
Now we check if there exists any left child for this node if so apply
the preorder procedure on the left subtree. Now check if there is any right
subtree for the node A, the preorder procedure is applied on the right
subtree. Since there exists a left subtree for node A, B is now considered as
the root of the left subtree of A and preorder procedure is applied. Hence
we find that B is processed next and then it is checked if B has a left
subtree. This recursive method is continued until all the nodes are visited.
Example for preorder traversal :
Step 1:
Step 2:
Step 3:
Step 4:
Step 5:
Step 6:
Step 2:
Step 3:
Step 4:
Step 5:
Step 6:
In the postorder traversal method the left subtree is visited first, then
the right subtree and at last the node element is processed. For example, A
is the root node. Since A has the left subtree the postorder traversal method
is applied recursively on the left subtree of A. Then when left subtree of A
is completely is processed, the postorder traversal method is recursively
applied on the right subtree of the node A. If right subtree is completely
processed, then the node element A is processed.
Example:
Step 1:
Step 2:
Step 3:
Step 4:
Step 5:
Step 6:
The NULL links of the roots left and right will be pointed to the head node
as follows
Next comes 8 now 8 is compared with root as it is less then attach 8 as the
left child of the root 10.
new - > left = root- > left
new - > right = root
root - > left = new
root - > lth = 1
The left link of node 8 points to its inorder predecessor and right link of the
node 8 points to its inorder successor.
Similarly, the next node 6 is attached to the left of the node 8. The next
node is 12 when compared with the root node 10 it is greater so we attach
the node 12 to the right of the root node 10 which is as follows.
Fig. 8.26: Inserting a node into Threaded Binary Tree as leaf node
If the right subtree of “s” is not empty, then this right subtree is
made the right subtree of “r” after insertion. Then “r” becomes inorder
predecessor of a node that has leftthread = = true and consequently there is
a thread which has to be updated to point to “r” . the node containing this
thread was previously the inorder successor of “s” .
1. Max Heap
2. Min Heap
Ever heap data structure will satisfy the following properties:
Property 1: [structure]
All levels in a heap must be full, except the last level and nodes must be
filled from left to right strictly.
Property 2: [ordering]
Nodes must be arranged in an order according to values based on max heap
or min heap.
8.6.3.1 What is Min Heap?
Definition for Min heap:
A min tree is a tree in which the key value in each node is no larger
than the key values in its children (if any). A min heap is a complete binary
tree that is also a min tree.
Example 1:
Now if we want to search for element 30. i.e., the key element will be
30. Compare the key element with root node, which is same so “element
found” will be displayed.
Example 2:
If we want to search for the key element 80 do the following process.
Now compare root with key i.e. 30<80 so not equal. Search in the right
subtree value with key element i.e., 48<80 so not equal. Search in the right
subtree value with the key value i.e., 80=80. Hence the key is found.
Example 2:
If we want to search for the key element 40 do the following process.
Compare the root and key i.e., 30<40 which is not equal. So, search in the
right subtree value with the key element i.e., 48>40. Now, search for the left
child i.e., NULL. Hence the element is not found.
Algorithm SEARCH( ROOT, k )
Temp = ROOT, par =NULL, loc = NULL
While temp ≠ NULL
If k = temp - > data
loc = temp
break
If k < temp - > data
par = temp
temp = temp - > left
else
par = temp
temp = temp - > right
8.7.2 How to insert into a Binary Search Tree?
Insertion into a Binary Search Tree (BST) will also perform in 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 new node with given value and set its left and right child as
NULL.
Step 2: Check weather tree is empty.
Step 3: If the tree is empty, then set the new node as root.
Step 4: If the tree is not empty, then check weather value of the new node is
smaller or larger than the node.
Step 5: If new node is smaller to the node, then move to the left child. If
new node is larger to the node, then move to the right child.
Step 6: Repeat the above step until we reach to a leaf node.
Step 7: After reaching to a leaf node, then insert the new node as left child
if new node is smaller else insert as right child.
Example 1 for insertion into Binary Search Tree:
Construct a Binary Search Tree with the following numbers.
10, 12, 40, 4, 20, 7, 5
Step 1: insert(10)
Since, the tree is empty make the new node as root.
Step 2: insert(12)
Since, 12>10 insert 12 as right child of 10.
Step 3: insert(40)
Since 10<40, move to right child. Then again 12<40, insert 40 as the
right child of 12.
Step 4: insert(4)
Since 4<10, insert 4 as left child of 10.
Step 5: insert(20)
Since 20>10, move to the right child. Again 20>12, move to the right
child. Then 20<40 move to left child. Here left child of 40 is NULL. Insert
20 directly as the left child of 40.
Step 6: insert(7)
Since 7<10, move to left child. As 7>4, insert as right child to 4.
Step 7: insert(5)
Since 5<10, move to left subtree. Again 5>4, move to right subtree.
Here since 5<7, insert 5 as left child to 7. So the final tree after insertion of
all elements is as follows.
From the above tree diagram the node we want to delete is the node
8, then we will set the left pointer of its parent (node 14) to NULL. Then
after deletion the binary search tree is as follows.
Steps of Algorithm to delete a node with one child in Binary Search Tree:
if(temp - > left !=NULL && temp - > right == NULL)
if(parent - > left ==temp)
parent - > left = temp - > left
else
parent - > right = temp - > left
temp == NULL
delete temp
8.7.3.3 How to delete a node with two children in Binary Search Tree?
The node if we want to delete is having two children.
From the diagram the node we want to delete is having the value 15
then we find the inorder successor of the node i.e., 40 will become the root
node. 3 will become the left child of root node 40 and its right child will be
80.
a) TwoWayJoin(small, big):
This joins only two Binary Search Tree small and big to obtain a single
Binary Search Tree. It is assumed that all keys of small are smaller than all
keys of big.
Example for TwoWayJoin(small, big) is shown below.
In the above graph G1 the length of path from (1, 4) is 1-2-4. So the length
from (1, 4) is 2.
Simple Path -A simple path is a path in which all vertices except possibly
the first and last are distinct. A path such that are the vertices are distinct,
except that the first and last could be the same is called as simple path.
The space required for representing a graph using its adjacency matrix
is n bits.The matrix is symmetric in case of undirected graph, while it may
2
struct head
{
char data;
struct head *down;
struct head *next;
};
struct node
{
char data;
struct node *next1;
}
Where, m is the boolean field to indicate weather the edge was examined or
not.
Consider the graph G as shown below.
Step 2: Start with the vertex from visiting S (starting node), and mark it as
visited.
Step 3: We then see an unvisited adjacent node from S . In this example, we
have three nodes but alphabetically we choose A , mark it as visited and
enqueue it.
Step 2: Mark S as visited and put it onto the stack. See any unvisited
adjacent node from S . We have three nodes and we can pick any of them.
For this example, we shall take the node in an alphabetical order.
Step 3: Mark A as visited and put it onto the stack. See any unvisited
adjacent node from A. Both S and D are adjacent to A but we are concerned
for unvisited nodes only.
Step 4: Visit D and mark it as visited and put onto the stack. Here, we have
B and C nodes, which are adjacent to D and both are unvisited. However,
we shall again choose in an alphabetical order.
Step 5: We choose B , mark it as visited and put onto the stack. Here B does
not have any unvisited adjacent node. So, we pop B from the stack.
Step 6: We check the stack top for return to the previous node and check if
it has any unvisited nodes. Here, we find D to be on the top of the stack.
Step 7: Only unvisited adjacent node is from D is C now. So we visit C ,
mark it as visited and put it onto the stack.
Step 8: So now we pop one by one node from stack until is empty.
9.6 What are Connected Components?
The maximal connected sub-graph of a graph is called connected
component of a graph. If a graph G is an undirected graph, then we can
determine the connectivity of the graph by simply calling either DFS or
BFS and determine if there are any unvisited vertex. We can identify the
connected components by repetitively calling either DFS(V) or BFS(V),
where V is a vertex that has not yet visited.
Consider a Graph as shown below.
Fig. 9.30: Connected Components
The connected sub-graph of a graph is below.
1.
For each vertex V in graph G do
2.
Create a set with the element V
3.
Initialize priority queue Q containing all the edges in descending
order of their weights
4.
Define forest = NULL
5.
while T has edges <= N-1 do
6.
Select an edge with minimum weight
7.
if T(v) T(u)
add (u,v) to forest
union T(v) and T(u)
8. return T.
To explain kruskal’s algorithm let us consider the following example:
Step1: Consider the Graph as shown below.
Step 4: Add the edges which has the least cost / weight order. We have to
consider edge weight 10 which connects the vertices 0 and 5.
Step 5: Add the edges which has the least cost / weight order. We have to
consider edge weight 12 which connects the vertices 2 and 3.
Step 6: Add the edges which has the least cost / weight order. We have to
consider edge weight 14 which connects the vertices 1 and 6.
Step 7: Add the edges which has the least cost / weight order. We have to
consider edge weight 16 which connects the vertices 1 and 2.
Step 7: Add the edges which has the least cost / weight order. We have to
consider edge weight 22 which connects the vertices 3 and 4.
Step 7: Add the edges which has the least cost / weight order. We have to
consider edge weight 25 which connects the vertices 4 and 5.
Step 2: Consider the least cost weighted edge 10 connecting the vertices 0
and 5.
Step 2: Connecting to the vertices 0 and 5 we have to consider the least cost
edge until it does not form a cycle. So connect least cost edge 25 with
connected vertices 4 and 5.
Step 2: Connecting to the vertices having the edges 10, 25 and 22. We have
to consider the least cost edge until it does not form a cycle. So connect
least cost edge 12 with connected vertices 2 and 3.
Step 2: Connecting to the vertices having the edges 10, 25, 22 and 12. We
have to consider the least cost edge until it does not form a cycle. So
connect least cost edge 16 with connected vertices 1 and 2.
Step 2: Connecting to the vertices having the edges 10, 25, 22, 12 and 16.
We have to consider the least cost edge until it does not form a cycle. So
connect least cost edge 14 with connected vertices 1 and 6.
Step 2:
Step 5: Consider the greedy approach for considering the edges of vertices
until it forms a cycle.
Step 2: Now consider A 0 , the path from i to j that contains the index value
less than or equal to 0.
A0 [2][1] = min(A-1 [2][1], A-1 [2][0] + A-1 [0][1]) =min(α, 3 + 4) = 7.
Step 3: Let us calculate A1 [i][j], here the index value should not exceed 1.
1. Insertion sort
2. Merge Sort
3. Quick Sort
4. Heap Sort
2) External Sorting:
If the data resides in secondary memory and is brought into main
memory in blocks for sorting and then result is returned back to secondary
memory is called external sorting. External sorting is required when the
data being sorted do not fit into the main memory.
The following are some external sorting techniques:
Step 3: Compare 20 with the elements in sorted zone and insert it in that
zone at appropriate position.
Step 4: Compare 50 with the elements in sorted zone and insert it in that
zone at appropriate position.
Step 5: Compare 40 with the elements in sorted zone and insert it in that
zone at appropriate position.
Step 6: Compare 10 with the elements in sorted zone and insert it in that
zone at appropriate position.
Step 7: Compare 60 with the elements in sorted zone and insert it in that
zone at appropriate position. Finally we get the sorted list of elements.
Step 5: As a[j] > pivot (i.e., 70>50). We will decrement j. We will continue
to decrement j until the element pointed by j is less than a[low].
Step 6: Now we cannot decrement j because 40 < 50. Hence, we will swap
a[i] and a[j] i.e., 90 and 40.
Step 7: As a[i] is less than a[low] and a[j] is greater than a[low] we will
continue incrementing i and decrementing j, until the false conditions are
obtained.
Step 9: As a[i] < a[low] and a[j] > a[low], we will continue incrementing I
and decrementing j.
Step 10: As a[j] < a[low] and j has crossed i, that is j < i, we will swap
a[low] and a[j].
Step 11: We will now start sorting left sublist, assuming the first element of
left sublist as pivot element. Thus now new pivot = 20.
Step 12: Now we will set i and j pointer and then we will start comparing
a[i] with a[low] or a[pivot]. Similarly comparision with a[j] and a[pivot].
Step 13: As a[i] > a[pivot], hence stop incrementing i. Now as a[j] >
a[pivot], hence decrement j.
Step 14: Now j cannot be decremented because 10 < 20. Hence we will
swap a[i] and a[j].
Step 16: Now as a[i] > a[low] or a[j] > a[pivot] decrement j.
Step 17: As a[j] < a[low] we cannot decrement j now. We will now swap
a[low] and a[j] as j has crossed i and i < j.
Step 18: As there is only one element in left sublist hence we will sort right
sublist.
Step 19: As left sublist is sorted completely we will sort right sublist,
assuming first element of right sublist as pivot.
Step 20: As a[i] < a[pivot], hence we will stop incrementing i. Similarly a[j]
< a[pivot], hence we stop decrementing j. Swap a[i] and a[j].
Step 24: The left sublist now contains 70 and right sublist contains only 90.
We cannot further subdivide the list.
1. Heap construction
2. Deletion of a Maximum element key
The heap is first constructed with the given ‘n’ numbers. The maximum
key value is deleted for ‘n -1’ times to the remaining heap. Hence we will
get the elements in decreasing order. The elements are deleted one by one
and stored in the array from last to first. Finally we get the elements in
ascending order.
The important points about heap sort technique are:
Step 3:
Step 4:
Step 5:
Step 6:
Step 7:
Step 8:
Step 9:
Step 10:
Step 11:
Step 12:
Step 13:
Step 14:
Step 15:
Step 16:
Step 17:
Step 18:
Step 19:
In fourth iteration.
Algorithm for Selection Sort:
SelectionSort(array, size)
repeat(size-1) times
set the first unsorted element as the minimum
for each of the unsorted elements
if element < currentMinimum
set element as newMinimum
swap minimum with first unsorted position
end selection sort
PROGRAM FOR SELECTION SORT:
#include<iostream.h>
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void printArray(int array[], int size) {
for (int i = 0; i < size; i++) {
cout << array[i] << " ";
}
cout << endl;
}
void selectionSort(int array[], int size) {
for (int step = 0; step < size - 1; step++) {
int min_idx = step;
for (int i = step + 1; i < size; i++) {
if (array[i] < array[min_idx])
min_idx = i;
}
swap(&array[min_idx], &array[step]);
}
}
int main() {
int data[] = {20, 13, 10, 15, 2};
int size = sizeof(data) / sizeof(data[0]);
selectionSort(data, size);
cout << "Sorted array in Acsending Order:\n";
printArray(data, size);
}
Time Complexity for Selection Sort:
Worst Case Complexity: O(n2)
If we want to sort in ascending order and the array is in descending order
then, the worst case occurs.
Best Case Complexity: O(n2)
It occurs when the array is already sorted
Average Case Complexity: O(n2)
It occurs when the elements of the array are in jumbled order i.e., neither
ascending nor descending.
10.7 What is Bubble Sort?
Bubble sort is the simplest kind of sorting method. We do the bubble
sort in several iterations called as passes.
Steps of Algorithm for Bubble Sort:
/*
Class Declaration
*/
class double_llist
{
public:
void create_list(int value);
void add_begin(int value);
void add_after(int value, int position);
void delete_element(int value);
void search_element(int value);
void display_dlist();
void count();
void reverse();
double_llist()
{
start = NULL;
}
};
/*
* Main: Conatins Menu
*/
int main()
{
int choice, element, position;
double_llist dl;
clrscr();
while (1)
{
cout<<endl<<"Operations on Doubly linked list"<<endl;
cout<<"1.Create Node\n2.Add at begining\n3.Add after
position\n4.Delete\n5.Display\n6.Count\n7.Reverse\n8.Quit"<<endl;
cout<<"Enter your choice : ";
cin>>choice;
switch ( choice )
{
case 1:
cout<<"Enter the element: ";
cin>>element;
dl.create_list(element);
cout<<endl;
break;
case 2:
cout<<"Enter the element: ";
cin>>element;
dl.add_begin(element);
cout<<endl;
break;
case 3:
cout<<"Enter the element: ";
cin>>element;
cout<<"Insert Element after postion: ";
cin>>position;
dl.add_after(element, position);
cout<<endl;
break;
case 4:
if (start == NULL)
{
cout<<"List empty,nothing to delete"<<endl;
break;
}
cout<<"Enter the element for deletion: ";
cin>>element;
dl.delete_element(element);
cout<<endl;
break;
case 5:
dl.display_dlist();
cout<<endl;
break;
case 6:
dl.count();
break;
case 7:
if (start == NULL)
{
cout<<"List empty,nothing to reverse"<<endl;
break;
}
dl.reverse();
cout<<endl;
break;
case 8:
exit(1);
default:
cout<<"Wrong choice"<<endl;
}
}
return 0;
}
/*
* Create Double Link List
*/
void double_llist::create_list(int value)
{
struct node *s, *temp;
temp = new(struct node);
temp->info = value;
temp->next = NULL;
if (start == NULL)
{
temp->prev = NULL;
start = temp;
}
else
{
s = start;
while (s->next != NULL)
s = s->next ;
s->next = temp;
temp->prev = s;
}
}
/*
* Insertion at the beginning
*/
void double_llist::add_begin(int value)
{
if (start == NULL)
{
cout<<"First Create the list."<<endl;
return;
}
struct node *temp;
temp = new(struct node);
temp->prev = NULL;
temp->info = value;
temp->next = start;
start->prev = temp;
start = temp;
cout<<"Element Inserted"<<endl;
}
/*
* Insertion of element at a particular position
*/
void double_llist::add_after(int value, int pos)
{
if (start == NULL )
{
cout<<"First Create the list."<<endl;
return;
}
struct node *tmp, *q;
int i;
q = start;
for (i = 0;i < pos - 1;i++)
{
q = q->next;
if (q == NULL)
{
cout<<"There are less than ";
cout<<pos<<" elements."<<endl;
return;
}
}
tmp = new(struct node);
tmp->info = value;
if (q->next == NULL)
{
q->next = tmp;
tmp->next = NULL;
tmp->prev = q;
}
else
{
tmp->next = q->next;
tmp->next->prev = tmp;
q->next = tmp;
tmp->prev = q ;
}
cout<<"Element Inserted"<<endl;
}
/*
* Deletion of element from the list
*/
void double_llist::delete_element(int value)
{
struct node *tmp, *q;
/*first element deletion*/
if (start->info == value)
{
tmp = start;
start = start->next;
start->prev = NULL;
cout<<"Element Deleted"<<endl;
free(tmp);
return;
}
q = start;
while (q->next->next != NULL)
{
/*Element deleted in between*/
if (q->next->info == value)
{
tmp = q->next;
q->next = tmp->next;
tmp->next->prev = q;
cout<<"Element Deleted"<<endl;
free(tmp);
return ;
}
q = q->next;
}
/*last element deleted*/
if (q->next->info == value)
{
tmp = q->next;
free(tmp);
q->next = NULL;
cout<<"Element Deleted"<<endl;
return;
}
cout<<"Element "<<value<<" not found"<<endl;
}
/*
* Display elements of Doubly Link List
*/
void double_llist::display_dlist()
{
struct node *q;
if (start == NULL)
{
cout<<"List empty,nothing to display"<<endl;
return;
}
q = start;
cout<<"The Doubly Link List is :"<<endl;
while (q != NULL)
{
cout<<q->info<<" <-> " ;
q = q->next;
}
cout<<"NULL"<<endl;
}
/*
* Number of elements in Doubly Link List
*/
void double_llist::count()
{
struct node *q = start;
int cnt = 0;
while (q != NULL)
{
q = q->next;
cnt++;
}
cout<<"Number of elements are: "<<cnt<<endl;
}
/*
* Reverse Doubly Link List
*/
void double_llist::reverse()
{
struct node *p1, *p2;
p1 = start;
p2 = p1->next;
p1->next = NULL;
p1->prev = p2;
while (p2 != NULL )
{
p2->prev = p2->next;
p2->next = p1;
p1 = p2;
p2 = p2->prev;
}
start = p1;
cout<<"List Reversed"<<endl;
}
OUTPUT:
Experiment 5: How to implement Binary Search
Tree through C++
AIM: To write a C++ program to implement Binary Search Tree.
Description:
Binary Search Tree, is a node-based binary tree data structure which has the
folllowing features.
● The left subtree of a node contains only nodes with keys less than the
node’s keys.
● The right subtree of a node contains only nodes with keys grater than
the node’s keys.
● The left and right subtree each must be also an binary tree.
● Search: Searches an element in a tree.
● Insert: Inserts an element in a tree.
● Pre-Order Traversal: Traverses a tree in a pre-ordered manner.
● Post-Order Traversal: Traverses a tree in post-order manner.
● Deletion: Deleting an element from the tree. In Deletion, again we
have three cases i.e., deletion of leaf node, deletion of node which has
only one child, deletion of the parent node having both the childern i.e.,
left and right child.
PROGRAM:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
class BST;//forward declaration.
class node{ // BST node declaration. Here each node has data and links to
left and right child.
friend class BST;
int info;
node *left;
node *right;
};
/* BST class declaration which contains the root node as data member and
different operarions on BST will be defined in this class*/
class BST
{
public:
node *root;
node* insert(node *,int);
void preorder(node *);
void postorder(node *);
void inorder(node *);
node* search(node *,int);
node* del(node *, int);
node* findmin(node*);
BST() // Default constructor which creates a empty tree
{
root=NULL;
}
};
node* BST::insert(node *ptr, int val)
/* insertion is a recursive function which accepts a ptr and element that
need to be inserted into the tree.*/
{
if(ptr==NULL)/* If ptr is NULL, then we can create a newnode and make
info as val and left and right child to NULL and return back*/
{
node *newnode= new node;
newnode->info=val;
newnode->left=newnode->right=NULL;
ptr=newnode;
}
else
{
if(ptr->info==val) // check value already exist or not. No duplicates are
allowed.
cout<<"Elements already in the tree\n";
else if(ptr->info < val) // if new value is greater than the node then move to
right of the tree
ptr->right=insert(ptr->right,val);
else //otherwise new value is less than the node then move to left of the tree
ptr->left=insert(ptr->left, val);
}
return ptr;
}
void BST::inorder(node *ptr) // func: Inorder traversing of tree i.e., left-
>root->right
{
if(ptr!=NULL)
{
inorder(ptr->left);
cout<<ptr->info<<"\t";
inorder(ptr->right);
}
}
void BST::postorder(node *ptr) // func: Post-order traversing of tree i.e.,
left-> right-> root
{
if(ptr!=NULL)
{
postorder(ptr->left);
postorder(ptr->right);
cout<<ptr->info<<"\t";
}
}
void BST::preorder(node *ptr) // func: Pre-order traversing of tree i.e., root-
>left ->right
{
if(ptr!=NULL)
{
cout<<ptr->info<<"\t";
preorder(ptr->left);
preorder(ptr->right);
}
}
node * BST::search(node *ptr,int ele) //func : Searching in the BST to find
whether element exist
{
if(ptr==NULL) // empty tree condition or element not found case
return NULL;
else if(ptr->info ==ele) // if element matches with the node data then return
the node .
return ptr;
else if(ptr->info<ele) // if node value is less than element then search in
right sub-tree.
return search(ptr->right,ele);
else // if node value is greater than element then search in left sub-tree.
return search(ptr->left,ele);
}
node * BST::del(node *ptr,int ele)
{
if(ptr==NULL)
return NULL; //empty tree condition
else if(ptr->info <ele)
ptr->right=del(ptr->right,ele);
else if(ptr->info >ele)
ptr->left=del(ptr->left,ele);
else if(ptr->left !=NULL && ptr->right!=NULL) //two children
{
node *tempmin=findmin(ptr->right);
ptr->info=tempmin->info;
ptr->right=del(ptr->right,tempmin->info);
}
else
{ // one or no child case
node *temp=ptr;
if(ptr->left==NULL)
ptr=ptr->right;
else if(ptr->right==NULL)
ptr=ptr->left;
else
delete temp;
}
return ptr;
}
node* BST::findmin(node *ptr)
/* To find the minimum node in the right subtree i.e., leftmost node in the
right subtree*/
{
if(ptr==NULL)
return NULL;
while(ptr->left!=NULL)
ptr=ptr->left;
return ptr;
}
int main()
{
int choice,val;
BST bst;
node *temp;
clrscr();
while(1)
{
cout<<"MAIN MENU\n 1: Insert an element\n 2: Inorder Traversal \n
3:Postorder traversal\n 4:Preorder Traversal \n 5:Deletion of element\n
6:Search an element\n 7:exit\n";
cout<<"Enter your choice:";
cin>>choice;
switch(choice)
{
case 1:cout<<"Enter the value to insert :";
cin>>val;
bst.root=bst.insert(bst.root,val);
break;
case 2:cout<<"Inorder Traversal of BST:\n";
bst.inorder(bst.root);
break;
case 3:cout<<"Postorder Traversal of BST:\n";
bst.postorder(bst.root);
break;
case 4:cout<<"Preorder Traversal of BST:\n";
bst.preorder(bst.root);
break;
case 5:cout<<"Enter an element to delete:";
cin>>val;
temp=bst.del(bst.root,val);
break;
case 6:cout<<"Enter an element to search:";
cin>>val;
temp=bst.search(bst.root,val);
if(temp==NULL)
cout<<"element not found";
else
cout<<"element found";
break;
case 7:exit(0);
default:cout<<" Wrong Choice.Try Again!!!!";
}
}
return 1;
}
OUTPUT:
Experiment 6: How to implement Heaps through
C++
AIM: To write a C++ program to implement Heaps
Description:
A Binary Heap is a Binary Tree with the following properties.
1. It’s a complete tree (All levels are completely filled except
possibly the last level and the last level has all keys as left as
possible). This property of Binary Heap makes them suitable to be
stored in an array.
2. A Binary Heap is either Min Heap or Max Heap. In a Min Binary
Heap, the key at root must be minimum among all keys present in
Binary Heap. The same property must be recursively true for all
nodes in Binary Tree. Max Binary Heap is similar to Min Heap.
PROGRAM:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
class MaxHeap // MaxHeap class declaration
{
private:
int *heap;
int heapSize;
int capacity;
public:
void Push(int);
void Pop();
void display();
MaxHeap(int n=20) // Constructor to initialize the capacity the heap
{
if(n<1)
cout<<"capacity must be >=1";
else
{
capacity=n;
heapSize=0;
heap= new int[capacity+1];
}
}
};
void MaxHeap::Push(int e)//func: To insert the element into the heap &
perform hepification
{
if(heapSize==capacity){
cout<<"Heap is full";
}
else
{
int currentNode=++heapSize;
while(currentNode!=1 && heap[currentNode/2]<e) // repeat until element
is less the current node/2 value
{
heap[currentNode]=heap[currentNode/2];
currentNode/=2;
}
heap[currentNode]=e;
}
}
void MaxHeap::Pop() // Delete the root from the max heap and perform
percolgate
{
if(heapSize<1)
{
cout<<"Heap is empty!!! Cannot Delete\n";
}
else
{
int last=heap[heapSize--]; // delete the last node and save it in last and place
it in the right position
int currentNode=1;
int child=2;
while(child<=heapSize)
{
if(child<heapSize && heap[child]<heap[child+1])
child++;
if(last>=heap[child])
break;
heap[currentNode]=heap[child];
currentNode=child;
child*=2;
}
heap[currentNode]=last;
}
}
void MaxHeap::display() // TO display elements in the heap
{
if(heapSize<1)
cout<<"No elements in Heap";
else
{
cout<<"Element in max heap are:";
for(int i=1;i<=heapSize;i++)
cout<<"\t"<<heap[i];
}
}
int main()
{
MaxHeap mh(30);
int ch,ele;
clrscr();
while(1)
{
cout<<":::::MainMenu::::";
cout<<"\n 1:Insert \n 2:Delete \n 3:Display \n 4:exit\n Enter your choice";
cin>>ch;
switch(ch)
{
case 1:cout<<"Enter an element to insert into max heap:";
cin>>ele;
mh.Push(ele);
break;
case 2:mh.Pop();
cout<<"element deleted";
break;
case 3:mh.display();
break;
case 4:exit(0);
default:cout<<"Wrong choice.Try Again!!!!!!";
}
}
}
OUTPUT:
Experiment 7: How to implement Breadth First
Search Techniques.
AIM: To write a C++ program to implement Breadth First Search.
Description:
Graph traverse means visiting every vertex and edge exactly once in a well-
defined order. Breadth-first search (BFS ) is an algorithm for traversing or
searching tree or graph data structures. It starts at the tree root (or some
arbitrary node of a graph, sometimes referred to as a 'search key') and
explores the neighbor nodes first, before moving to the next level
neighbours.BFS and its application in finding connected components of
graphs
PROGRAM:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int cost[10][10],i,j,k,n,qu[10],front,rare,v,visit[10],visited[10];
main()
{
int m;
clrscr();
cout<<"enterno of vertices";
cin>> n;
cout<<"ente no of edges";
cin>> m;
cout<<"\nEDGES \n";
for(k=1;k<=m;k++)
{
cin>>i>>j;
cost[i][j]=1;
}
cout<<"enter initial vertex";
cin>>v;
cout<<"Visitied vertices\n";
cout<< v;
visited[v]=1;
k=1;
while(k<n)
{
for(j=1;j<=n;j++)
if(cost[v][j]!=0 && visited[j]!=1 && visit[j]!=1)
{
visit[j]=1;
qu[rare++]=j;
}
v=qu[front++];
cout<<v << " ";
k++;
visit[v]=0; visited[v]=1;
}
}
OUTPUT:
Experiment 8: How to implement Depth First
Search Technique through C++
AIM: To write a C++ program to implement Depth First Search
Technique.
Description:
Graph traverse means visiting every vertex and edge exactly once in a well-
defined order. Depth-first search (DFS ) is an algorithm for traversing or
searching tree or graph data structures. One starts at the root (selecting
some arbitrary node as the root in the case of a graph) and explores as far as
possible along each branch before backtracking.
PROGRAM:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int cost[10][10],i,j,k,n,stk[10],top,v,visit[10],visited[10];
main()
{
int m;
clrscr();
cout<<"enterno of vertices";
cin>> n;
cout<<"ente no of edges";
cin>> m;
cout<<"\nEDGES \n";
for(k=1;k<=m;k++)
{
cin>>i>>j;
cost[i][j]=1;
}
cout<<"enter initial vertex";
cin>>v;
cout<<"ORDER OF VISITED VERTICES";
cout<< v <<" ";
visited[v]=1;
k=1;
while(k<n)
{
for(j=n;j>=1;j--)
if(cost[v][j]!=0 && visited[j]!=1 && visit[j]!=1)
{
visit[j]=1;
stk[top]=j;
top++;
}
v=stk[--top];
cout<<v << " ";
k++;
visit[v]=0; visited[v]=1;
}
}
OUTPUT:
Experiment 9: How to implement Prim’s
Algorithm through C++
AIM: To write a C++ program to implement Prim’s Algorithm.
Description:
Prim's algorithm is a greedy algorithm that finds a minimum spanning tree
for a weighted undirected graph. This means it finds a subset of the edges
that forms a tree that includes every vertex, where the total weight of all the
edges in the tree is minimized. The algorithm operates by building this tree
one vertex at a time, from an arbitrary starting vertex, at each step adding
the cheapest possible connection from the tree to another vertex.
PROGRAM:
#include <iostream.h>
#include <conio.h>
#define ROW 7
#define COL 7
#define infi 5000 //infi for infinityclass prims
typedef int bool;
const bool true=1, false=0;
struct prims
{
int graph[ROW][COL],nodes;
public:
prims();
void createGraph();
void primsAlgo();
};
prims :: prims(){
for(int i=0;i<ROW;i++ )
for(int j=0;j<COL;j++)
graph[i][j]=0;
}
for(i=0;i<nodes;i++)
selected[i]=false;
selected[0]=true;
ne=0 ;
for(i=0;i<nodes;i++)
{
if(selected[i]==true){
for(j=0;j<nodes;j++){
if(selected[j]==false){
if(min > graph[i][j])
{
min=graph[i][j];
x=i;
y=j;
}
}
}
}
}
selected[y]=true;
cout<<"\n"<<x+1<<" --> "<<y+1;
ne=ne+1;
}
}
void main()
{
prims MST;
clrscr();
cout<<"\nPrims Algorithm to find Minimum Spanning Tree\n";
MST.createGraph();
MST.primsAlgo() ;
getch();
}
OUTPUT:
Experiment 10: How to implement Dijkstra’s
Algorithm through C++
AIM: To write a C++ program to implement Dijkstra’s Algorithm.
Description:
Dijkstra's algorithm is an algorithm for finding the shortest paths between
nodes in a graph. For a given source node in the graph, the algorithm finds
the shortest path between that node and every other. It can also be used for
finding the shortest paths from a single node to a single destination node by
stopping the algorithm once the shortest path to the destination node has
been determined.
PROGRAM:
#include<iostream.h>
#include<conio.h>
typedef int bool;
const bool true=1, false=0;
class Dijkstra{
int cost[20][20],v,n,dist[20];
public:
void dijkstra() //func: to findout the shortest path from source to all other
vertices
{
bool s[20];
int i,u,w,j,min=9999;
for(i=1;i<=n;i++)//initial distance from source to other vertices
{
s[i]=false;
dist[i]=cost[v][i];
}
s[v]=true;
dist[v]=0;
for(i=2;i<=n;i++) // To find out the next non-visited minimum vertex
{
min=9999;
for(j=1;j<=n;j++)
{
if(i==j || s[j]==true)
continue;
else
if(min>dist[j])
u=j;
}
s[u]=true;
for(j=1;j<=n;j++)
{
if(s[j]==false) //if the vertex is not visited then calculate and compare the
present and previous distances
{
if(dist[j]>dist[u]+cost[u][j])
dist[j]=dist[u]+cost[u][j];
}
}
}
}
void read() // func read(): To read the cost adjacency matrix data
{
cout<<"\n enter number of vertices:";
cin>>n;
cout<<"\n enter the source node:";
cin>>v;
cout<<":::enter 9999 for infinity:::\n";
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<"enter the lenght["<<i<<"]["<<j<<"]:";
cin>>cost[i][j];
}
}
}
void display() // Display all the shortest distances from the source to the
other vertices.
{
for(int i=1;i<=n;i++)
cout<<"\n Shortest path from source "<<v<<"to "<<i<<" node is :"
<<dist[i];
}
};
int main()
{
Dijkstra d;
clrscr();
d.read();
d.dijkstra();
d.display();
}
OUTPUT:
Experiment 11: How to implement Kruskal’s
Algorithm through C++
AIM: To write a C++ program to implement Kruskal’s Algorithm.
Description: Kruskal's algorithm is a minimum-spanning-tree algorithm
which finds an edge of the least possible weight that connects any two trees
in the forest. It is a greedy algorithm in graph theory as it finds a minimum
spanning tree for a connected weighted graph adding increasing cost arcs at
each step. This means it finds a subset of the edges that forms a tree that
includes every vertex, where the total weight of all the edges in the tree is
minimized. If the graph is not connected, then it finds a minimum spanning
forest (a minimum spanning tree for each connected component).
PROGRAM:
#include<iostream.h>
#include<conio.h>
class Kruskal
{
int parent[20],n,cost[20][20],t[20][3];
public:
void read() // to read the cost-adjacency matrix data
{
cout<<"\n enter number of vertices for given graph:";
cin>>n;
cout<<"enter 9999 for infinity\n";
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<"\nenter the cost["<<i<<"]["<<j<<"]:";
cin>>cost[i][j];
}
}
}
int kruskal()
{
int i,j,min,a,b,cnt,mincost=0,u,v;
clrscr();
for(i=1;i<=n;i++) //initially all vertex parent is -1
parent[i]=-1;
cnt=1;
cout<<"Resultant spanning tree:";
while(cnt<n)
{
for(i=1,min=9999;i<=n;i++) //finding out the minimum cost edge from the
graph
{
for(j=1;j<=n;j++)
{
if(cost[i][j]==0)
break;
else
if(min > cost[i][j])
{
min=cost[i][j];
u=i;
v=j;
}
}
}
a=find(u); //find will return the parent node of given vertex
b=find(v);
if(a!=b) //parents are not equal then visit that edge and union the edge
vertex
{
cnt++;
t[i][1]=u;
t[i][2]=v;
mincost=mincost+cost[u][v];
uni(a,b);
cout<<u<<" ,"<<v<<"\n";
}
cost[u][v]=cost[v][u]=999;
}
return mincost;
}
int find(int i) //return the parent node of i
{
while(parent[i]>=0)
i=parent[i];
return i;
}
void uni(int i,int j) // joins two vertex with parent child relationship –help to
check not to form cycles.
{
parent[i]=j;
}
};
int main()
{
Kruskal k;
clrscr();
k.read();
int e=k.kruskal();
cout<<"\n The minimum cost of the spanning tree is:"<<e<<"\n";
}
OUTPUT:
Experiment 12: How to implement Merge Sort
though C++
AIM: To write a C++ program to implement Merge Sort.
Description:
Merge Sort is a Divide and Conquer algorithm. It divides input array in two
halves, calls itself for the two halves and then merges the two sorted halves.
The merge() function is used for merging two halves. The merge(arr, l, m,
r) is key process that assumes that arr[l..m] and arr[m+1..r] are sorted and
merges the two sorted sub-arrays into one.
PROGRAM:
#include<iostream.h>
#include<conio.h>
class Merge_Sort
{
private:
int *a,*b;
public:
int len;
void read() // reads the array data
{
int i;
cout<<"Enter the lenght of Array:";
cin>>len;
a=new int[len];
b=new int[len];
for(i=1;i<=len;i++)
{
cout<<"Enter the Element a["<<i<<"]:";
cin>>a[i];
}
}
void display() // to display array elements
{
int i;
if(len==0)
cout<<"Array is Empty";
else
{
cout<<"Array Elements are:";
for(i=1;i<=len;i++)
cout<<a[i]<<"\t";
cout<<"\n";
}
}
void MergeSort(int left,int right) //To divide the array to two halfs and
joining it back
{
if(left<right)
{
int mid=(left+right)/2;
MergeSort(left,mid);
MergeSort(mid+1,right);
Merge(left,mid,right);
}
}
void Merge(int low,int mid,int high)//takes to halves and join them in the
sorted order
{
int i,j,k,h;
h=low;
i=low;
j=mid+1;
while(i<=mid && j<=high)
{
if(a[i]>a[j])
{
b[h]=a[j];
h++;
j++;
}
else
{
b[h]=a[i];
h++;
i++;
}
}
while(i<=mid)//remaining element in left side
{
b[h]=a[i];
h++;
i++;
}
while(j<=high)//remaining elements in right half
{
b[h]=a[j];
h++;
j++;
}
for(k=low;k<=high;k++)
a[k]=b[k];
}
};
int main()
{
Merge_Sort ms;
clrscr();
ms.read();
cout<<"::::Array before Sorting::::\n";
ms.display();
ms.MergeSort(1,ms.len);
cout<<"\n::::Array After Sorting::::\n";
ms.display();
return(0);
}
OUTPUT:
Experiment 13: How to implement Quick Sort
through C++
AIM: To write a C++ program to implement Quick Sort.
Description:
QuickSort is a Divide and Conquer algorithm. It picks an element as pivot
and partitions the given array around the picked pivot.(Always pick first
element as pivot). The key process in quickSort is partition(). Target of
partitions is, given an array and an element x of array as pivot, put x at its
correct position in sorted array and put all smaller elements (smaller than x)
before x, and put all greater elements (greater than x) after x. All this should
be done in linear time.
PROGRAM:
#include<iostream.h>
#include<conio.h>
class Quick_Sort
{
private:
int *a;
public:
int len;
Quick_Sort()
{
len=0;
}
void read() //read the array data
{
int i;
cout<<"Enter lenght of the array:";
cin>>len;
a=new int[len];
for(i=1;i<=len;i++)
{
cout<<"Enter the value:a["<<i<<"]:";
cin>>a[i];
}
}
void display() // To display the array elements
{
int i;
if(len==0)
cout<<"Array is Empty";
else
{
cout<<"Array Elements are:";
for(i=1;i<=len;i++)
cout<<a[i]<<"\t";
cout<<"\n";
}
}
void quicksort(int left,int right) //dividing the elements into two halves at
the pivot position
{
if(left<right)
{
int j;
j=partition(left,right+1);
quicksort(left,j-1);
quicksort(j+1,right);
}
}
int partition(int l,int r)// placing the pivot at the right position
{
int pivot,i,j,temp;
pivot=a[l];
i=l;
j=r;
do
{
do
{
i++;
}while(a[i]<pivot);
do
{
j--;
}while(a[j]>pivot);
if(i<j)//Swap element at position i and j
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}while(i<=j);
a[l]=a[j];
a[j]=pivot;
return(j);
}
};
int main()
{
Quick_Sort qs;
clrscr();
qs.read();
cout<<"\n::::Array before sorting::::\n";
qs.display();
qs.quicksort(1,qs.len);
cout<<"\n::::Array After Sorting::::\n";
qs.display();
return(0);
}
OUTPUT:
Experiment 14: How to implement Data
Searching using Divide and Conquer Technique
through C++
AIM: To write a C++ program to implement Data Searching using Divide
and Conquer Technique.
Description:
Binary Search is applied on the sorted array or list. In binary search, we
first compare the value with the elements in the middle position of the
array. If the value is matched, then we return the value. If the value is less
than the middle element, then it must lie in the lower half of the array and if
it's greater than the element then it must lie in the upper half of the array.
We repeat this procedure on the lower (or upper) half of the array. Binary
Search is useful when there are large numbers of elements in an array.
PROGRAM:
#include<iostream.h>
#include<conio.h>
class DataSearch
{
private:
int *a;
int n;
public:
DataSearch(int x)
{
n=x;
a= new int[n];
}
void read() //to read the array data
{
int i;
cout<<"Enter elements in ascending order:\n";
for(i=0;i<n;i++)
{
cout<<"Enter element a["<<i<<"]:";
cin>>a[i];
}
}
int RecSearch(int low,int high,int ele) // recursively searching the element
in the array.
{
if(low<=high)
{
int mid=(low+high)/2;
if(a[mid]==ele) //if element found, return the value
return mid;
else if(a[mid]>ele) //if element is less than mid then search in left side to
mid
return RecSearch(low,mid-1,ele);
else //otherwise search to the right of the mid
return RecSearch(mid+1,high,ele);
}
return -1; //if element not found
}
};
int main()
{
int n,ele,c;
cout<<"Enter the range of the array:";
cin>>n;
DataSearch ds(n);
ds.read();
cout<<"Enter the element to found:";
cin>>ele;
c=ds.RecSearch(0,n-1,ele);
if(c==-1)
cout<<"Element not found ...";
else
cout<<"Element "<<ele<<"is found at position at "<<c<<"\n";
return 0;
}
OUTPUT:
OTHER BOOKS BY AUTHOR: