You are on page 1of 68

TYIT 2 B 190410116114

PRACTICAL 1
Aim: Implementation and Time Analysis of Sorting Algorithms.
1. Bubble Sort
 Description
 It is a simple sorting algorithm that works by
 Comparing each pair of adjacent items and swapping them if they are
in the wrong order.
 The pass through the list is repeated until no swaps are needed, which
indicates that the list is sorted.
 As it only uses comparisons to operate on elements, it is a comparison
sort.
 Although the algorithm is simple, it is too slow for practical use.

 Algorithm
int flag=1;
for(i = 1; i < n; i++)
for(j = 1; j < n-i; j++)
if(A[j] > A[j+1])
flag=0;
swap(A[j],A[j+1])
if(flag == 1)
cout<<"already sorted"<<endl
break;

 Program
#include<stdio.h>
#include<conio.h>

void main()
{
int n, i, j, a[30], temp;
printf("\nEnter total: ");
scanf("%d",&n);

printf("\nEnter array elements: ");


for(i=0;i<n;i++)
scanf("%d",&a[i]);

int flag = 1;
for(i=0;i<n;i++)
{
for(j=0;j<n-i-1;j++)
{

Page 1
TYIT 2 B 190410116114

if (a[j] > a[j+1])


{
flag = 0;
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
if (flag == 1)
{
printf("\nSorted");
break;
}
}

printf("\nSorted array is: ");


for(i=0;i<n;i++)
printf(" %d",a[i]);
}

 Output

Page 2
TYIT 2 B 190410116114

 Time Complexity
 Worst Case Time Complexity : O(n2)
 Best Case Time Complexity :  Ω (n)
 Average Time Complexity:  θ (n2)
 Space Complexity: O(1)

2. Selection Sort
 Description
 Selection sort divides the array or list into two parts,
 The sorted part at the left end
 and the unsorted part at the right end.
 Initially, the sorted part is empty and the unsorted part is the entire
list.
 The smallest element is selected from the unsorted array and
swapped with the leftmost element, and that element becomes a part
of the sorted array.
 Then it finds the second smallest element and exchanges it with the
element in the second leftmost position.
 This process continues until the entire array is sorted.

 Algorithm
for i ← 1 to n-1 do
minj ← i;
minx ← A[i];
for j ← i + 1 to n do
if A[j] < minx then
minj ← j;
minx ← A[j];
A[minj] ← A[i];
A[i] ← minx;

 Program
#include<stdio.h>
#include<conio.h>

void main()
{
int n, i, j, a[30], minj,minx;
printf("\nEnter total: ");
scanf("%d",&n);

Page 3
TYIT 2 B 190410116114

printf("\nEnter array elements: ");


for(i=0;i<n;i++)
scanf("%d",&a[i]);

for(i=0;i<n-1;i++)
{
minj = i;
minx = a[i];
for(j=i+1;j<n;j++)
{
if (a[j] < minx)
{
minj = j;
minx = a[j];
}
}
a[minj] = a[i];
a[i] = minx;
}

printf("\nSorted array is: ");


for(i=0;i<n;i++)
printf(" %d",a[i]);
}

 Output

Page 4
TYIT 2 B 190410116114

 Time Complexity
 Worst Case Time Complexity : O(n^2)
 Best Case Time Complexity :  Ω(n^2)
 Average Time Complexity :  θ(n^2)
 Space Complexity: O(1)

3. Insertion Sort
 Description
 Insertion sort works similarly as we sort cards in our hand in a card
game.
 We assume that the first card is already sorted then, we select an
unsorted card. If the unsorted card is greater than the card in hand, it
is placed on the right otherwise, to the left. In the same way, other
unsorted cards are taken and put at their right place.
 A similar approach is used by insertion sort.
 Insertion sort is a sorting algorithm that places an unsorted element
at its suitable place in each iteration.

 Algorithm
for i ← 2 to n do
x ← T[i];
j ← i - 1;
while x < T[j] and j > 0 do
T[j+1] ← T[j];
j ← j – 1;
T[j+1] ← x;

 Program
#include<stdio.h>
#include<conio.h>

void main()
{
int n, i, j, a[30], x;
printf("\nEnter total: ");
scanf("%d",&n);

printf("\nEnter array elements: ");


for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}

Page 5
TYIT 2 B 190410116114

for(i=1;i<n;i++)
{
x = a[i];
j = i-1;
while(x < a[j] && j >= 0)
{
a[j+1] = a[j];
j = j-1;
}
a[j+1] = x;
}

printf("\nSorted array is: ");


for(i=0;i<n;i++)
{
printf(" %d",a[i]);
}
}

 Output

 Time Complexity
 Worst Case Time Complexity : O(n^2)
 Best Case Time Complexity :  Ω(n)
 Average Time Complexity :  θ(n^2)
 Space Complexity: O(1)

Page 6
TYIT 2 B 190410116114

4. Counting Sort
 Description
 Counting sort is a sorting algorithm that sorts the elements of an array
by counting the number of occurrences of each unique element in the
array.
 The count is stored in an auxiliary array and the sorting is done by
mapping the count as an index of the auxiliary array.
 This sorting technique is effective when the difference between
different keys are not so big, otherwise, it can increase the space
complexity.

 Algorithm
for i ← 1 to k do
    c[i] ← 0
for j ← 1 to n do
    c[A[j]] ← c[A[j]] + 1
for i ← 2 to k do
    c[i] ← c[i] + c[i-1]
for j ← n downto 1 do
    B[c[A[j]]] ← A[j]
    c[A[j]] ← c[A[j]] – 1

 Program
#include<stdio.h>
#include<conio.h>

void main()
{
int n, i, j, a[30],k=0;

printf("\nEnter total: ");


scanf("%d",&n);

printf("\nEnter array elements: ");


for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if (a[i] > k)
k = a[i];
}

int c[k],b[n];
for(i=0;i<=k;i++)

Page 7
TYIT 2 B 190410116114

c[i] = 0;
for(j=1;j<=n;j++)
c[a[j]] = c[a[j]] + 1;
for(i=1;i<=k;i++)
c[i] = c[i] + c[i-1];
for(j=n;j>=1;j--)
{
b[c[a[j]]] = a[j];
c[a[j]] = c[a[j]] - 1;
}

printf("\nSorted array is: ");


for(i=1;i<=n;i++)
printf(" %d",b[i]);
}

 Output:

 Time Complexity
 Worst Case Time Complexity : O(max+size)
 Best Case Time Complexity :  Ω(max+size)
 Average Time Complexity :  θ(max+size)
 Space Complexity: O(max)

Page 8
TYIT 2 B 190410116114

PRACTICAL 2
Aim: Implementation and Time Analysis of Sorting Algorithms and
Binary Search Algorithm.
1. Merge Sort
 Description
 Merge Sort is a kind of Divide and Conquer algorithm in computer
programming.
 It is one of the most popular sorting algorithms and a great way to
develop confidence in building recursive algorithms.
 Using the Divide and Conquer technique, we divide a problem into sub
problems. When the solution to each sub problem is ready, we
'combine' the results from the sub problems to solve the main
problem.
 The Merge Sort function repeatedly divides the array into two halves
until we reach a stage where we try to perform Merge Sort on a
subarray of size 1.
 Algorithm
mergesort(A,lb,ub)
if(lb<ub)

mid=(lb+ub)/2;
mergesort(A,lb,mid)
mergesort(A,mid+1,ub)
merge(A, lb, mid ,ub)
merge(A,lb,mid,ub) (main back born of merge sort)
i ← lb;
j ← mid+1;
K ← ub
While i<=mid && j<=ub
if A[i]<=A[j]
B[k]=A[i] and i++, k++
else
B[k]=A[j] and j++, k++
If i>mid (when size of list in j is larger than i)
while(j<=ub)
B[k]=A[j] and j++,k++
Else (when size of list in i is larger than j)
while(i<=mid)
B[k]=A[i] and i++,k++
For k is lb to ub
A[k]=B[k]

Page 9
TYIT 2 B 190410116114

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

void merge(int arr[], int l, int m, int r)


{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;

int L[n1], R[n2];

for (i = 0; i < n1; i++)


L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];

i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
}
else {
arr[k] = R[j];
j++;
}
k++;
}

Page 10
TYIT 2 B 190410116114

while (i < n1) {


arr[k] = L[i];
i++;
k++;
}

while (j < n2) {


arr[k] = R[j];
j++;
k++;
}
}

void mergeSort(int arr[], int l, int r)


{
if (l < r) {

int m = l + (r - l) / 2;

mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);

merge(arr, l, m, r);
}
}

void printArray(int A[], int size)


{
int i;
for (i = 0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}

Page 11
TYIT 2 B 190410116114

int main()
{
int arr[30];
int n;
printf("Enter total: ");
scanf("%d", &n);
printf("Enter array elements: ");
for(int i=0;i<n;i++)
scanf("%d", &arr[i]);

mergeSort(arr, 0, n - 1);
printf("\nSorted array is \n");
printArray(arr, n);
return 0;
}

 Output

 Time Complexity
 Worst Case Time Complexity : O(n*log n)
 Best Case Time Complexity :  Ω (n*log n)
 Average Time Complexity :  θ (n*log n)
 Space Complexity: O(n)

Page 12
TYIT 2 B 190410116114

2. Quick Sort
 Description
 Quick sort is an algorithm based on divide and conquer approach in
which the array is split into subarrays and these sub-arrays are
recursively called to sort the elements.
 The array is divided into subparts taking pivot as the partitioning
point. The elements smaller than the pivot are placed to the left of the
pivot and the elements greater than the pivot are placed to the right.
 The left and the right subparts are again partitioned using the by
selecting pivot elements for them. This can be achieved by recursively
passing the subparts into the algorithm.
 This step does not play a significant role in quicksort. The array is
already sorted at the end of the conquer step.

 Algorithm
quicksort(T[i,…,j])
{ Sorts subarray T[i,…,j] into ascending order }
if j – i is sufficiently small
then insert (T[i,…,j])
else
pivot(T[i,…,j],l)
quicksort(T[i,…,l - 1])
quicksort(T[l+1,…,j]
pivot(T[i,…,j]; var l)
p ← T[i]
k←i
l←j+1
repeat k ← k+1 until T[k] > p or k ≥ j
repeat l ← l-1 until T[l] ≤ p
while k < l do
Swap T[k] and T[l]
Repeat k ← k+1 until T[k] > p
Repeat l ← l-1 until T[l] ≤ p
Swap T[i] and T[l]

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

void swap(int* a, int* b)


{
int t = *a;
Page 13
TYIT 2 B 190410116114

*a = *b;
*b = t;
}

int partition (int arr[], int low, int high)


{
int pivot = arr[high];
int i = (low - 1);

for (int j = low; j <= high- 1; j++)


{

if (arr[j] < pivot)


{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}

void quickSort(int arr[], int low, int high)


{
if (low < high)
{

int pi = partition(arr, low, high);

quickSort(arr, low, pi - 1);


quickSort(arr, pi + 1, high);
}
}

void printArray(int arr[], int size)


{
int i;
for (i=0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}

Page 14
TYIT 2 B 190410116114

int main()
{
int arr[30];
int n;
printf("Enter total: ");
scanf("%d", &n);
printf("Enter array elements: ");
for(int i=0;i<n;i++)
scanf("%d", &arr[i]);
quickSort(arr, 0, n-1);
printf("Sorted array: ");
printArray(arr, n);
return 0;
}

 Output

 Time Complexity
 Worst Case Time Complexity : O(n^2)
 Best Case Time Complexity :  Ω (n*log n)
 Average Time Complexity :  θ (n*log n)
 Space Complexity: O (n*log n)

3. Binary Search
 Description
 Search a sorted array by repeatedly dividing the search interval in half.
Begin with an interval covering the whole array.

Page 15
TYIT 2 B 190410116114

 If the value of the search key is less than the item in the middle of the
interval, narrow the interval to the lower half.
 Otherwise narrow it to the upper half. Repeatedly check until the value
is found or the interval is empty.

 Algorithm
Function biniter(T[1,…,n], x)
if x > T[n] then return n+1
i ← 1;
j ← n;
while i < j do
k ← (i + j ) ÷ 2
if x ≤ T [k] then j ← k
else i ← k + 1
return i
Function binsearch(T[1,…,n], x)
if n = 0 or x > T[n] then return n + 1
else return binrec(T[1,…,n], x)
Function binrec(T[i,…,j], x)
if i = j then return i
k ← (i + j) ÷ 2
if x ≤ T[k] then
return binrec(T[i,…,k],x)
else return binrec(T[k + 1,…,j], x)

 Program (Iterative)
#include<stdio.h>

void main()
{
int a[20],n,start,end,mid,i,x;
printf("Enter total: ");
scanf("%d",&n);
printf("\nEnter array elements: ");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("Enter element to be found: ");
scanf("%d",&x);
start = a[0];
end = a[n-1];

while(start<end)
{
mid = (start+end)/2;

Page 16
TYIT 2 B 190410116114

if(a[mid]==x)
printf("%d is at %d position",x,mid);
if(a[mid]<x)
start = mid+1;
else
end = mid;
}
}

 Output:

 Program (Recursive)
#include<stdio.h>

int BinarySearch(int a[], int start, int end, int x)


{
if(start<=end)
{
int mid = (start+end)/2;
if(a[mid]==x)
return mid;
if(a[mid]<x)
return BinarySearch(a, mid+1, end, x);
return BinarySearch(a, start, mid-1, x);
}
return 0;

Page 17
TYIT 2 B 190410116114

void main()
{
int a[20],n,i,x,res;
printf("Enter total: ");
scanf("%d",&n);
printf("\nEnter array elements: ");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("Enter element to be found: ");
scanf("%d",&x);
res = BinarySearch(a,0,n-1,x);
printf("%d is present at %d position",x,res);
}

 Output

 Time Complexity
 log2 (n)
 Space Complexity: O(1)

Page 18
TY IT 2 B 190410116114

PRACTICAL 3
Aim: Implementation of Max Heap Sort algorithm.
1. Max Heap Sort
 Description
 A heap data structure is a binary tree with the following two properties.
 It is a complete binary tree: Each level of the tree is completely filled, except
possibly the bottom level. At this level it is filled from left to right.
 It satisfies the heap order property: the data item stored in each node is
greater than or equal to the data item stored in its children node.
 Max-Heap − Where the value of the root node is greater than or equal to
either of its children.
 Min-Heap − Where the value of the root node is less than or equal to either of
its children.

 Algorithm

Heap_Sort(A[1,….,n])

Build-Max-Heap(A)

for I  length[A] downto 2

do exchange A[1] <--> A[i]

heap-size[A] heap-size[A] -1

Max-Heapify(A,i,n)

Max-Heapify(A,i,n)

l left(i)

rright(i)

if l <= n and A[l] > A[i]

then largest l

else largest i

if r <= n and A[r] > A[largest]

then largest r

Page 19
TY IT 2 B 190410116114

if largest != i

then exchange A[i] <--> A[largest]

Max-Heapify(A, largest, n)

 Program

#include<stdio.h>

#include <stdlib.h>

void swap(int *a, int *b) {

int temp = *a;

*a = *b;

*b = temp;

void heapify(int arr[], int n, int i) {

int largest = i;

int left = 2 * i + 1;

int right = 2 * i + 2;

if (left < n && arr[left] > arr[largest])

largest = left;

Page 20
TY IT 2 B 190410116114

if (right < n && arr[right] > arr[largest])

largest = right;

if (largest != i) {

swap(&arr[i], &arr[largest]);

heapify(arr, n, largest);

void heapSort(int arr[], int n) {

for (int i = n / 2 - 1; i >= 0; i--)

heapify(arr, n, i);

for (int i = n - 1; i >= 0; i--) {

swap(&arr[0], &arr[i]);

Page 21
TY IT 2 B 190410116114

heapify(arr, i, 0);

int main() {

int n,arr[30],i,j;

printf("Enter size of array: ");

scanf("%d",&n);

printf("Enter array elements: ");

for(i=0;i<n;i++)

scanf("%d",&arr[i]);

heapSort(arr, n);

printf("Sorted array is \n");

for ( j = 0; j < n; j++)

printf("%d ", arr[j]);

printf("\n");

Page 22
TY IT 2 B 190410116114

 Output:

 Time Complexity

Time Complexity: O(nlogn)

Page 23
TY IT 2 B 190410116114

PRACTICAL 4
Aim: Implementation and Time analysis of factorial program using
iterative and recursive method.
1. Factorial Program
 Description
 Factorial of a non-negative integer, is multiplication of all integers
smaller than or equal to n. For example factorial of 6 is 6*5*4*3*2*1
which is 720.

 The function is used, among other things, to find the number of way
“n” objects can be arranged.

 There are n! ways of arranging n distinct objects into an ordered


sequence.

 Algorithm
 Recursive Algorithm
Fact(n)

Begin

if n == 0 or 1 then

Return 1;

else

Return n*Call Fact(n-1);

endif

End

 Iterative Algorithm
int factorial( int N )

int product = 1;

for ( int j=1; j<=N; j++ )

product *= j;

return product;

Page 24
TY IT 2 B 190410116114

 Program
 Recursive
#include <stdio.h>

unsigned int factorial(unsigned int n)

if (n == 0)

return 1;

return n * factorial(n - 1);

int main()

int num;

printf("Enter no.: ");

scanf("%d", &num);

printf("Factorial of %d is %d", num, factorial(num));

return 0;

 Iterative
#include <stdio.h>

unsigned int factorial(unsigned int n)

int res = 1, i;

for (i = 2; i <= n; i++)

res *= i;
Page 25
TY IT 2 B 190410116114

return res;

int main()

int num;

printf("Enter no.: ");

scanf("%d",&num);

printf(

"Factorial of %d is %d", num, factorial(num));

return 0;

 Output

 Time Complexity
Time Complexity: O(n)

Page 26
TY IT 2 B 190410116114

PRACTICAL 5
Aim: Implementation of a knapsack problem using dynamic
programming.
A. Knapsack Problem
 Description
 Given weights and values of n items, put these items in a knapsack of
capacity W to get the maximum total value in the knapsack.

  In other words, given two integer arrays val[0..n-1] and wt[0..n-1]
which represent values and weights associated with n items
respectively. 

 Also given an integer W which represents knapsack capacity, find out


the maximum value subset of val[] such that sum of the weights of this
subset is smaller than or equal to W.

 You cannot break an item, either pick the complete item or don’t pick
it (0-1 property).

 Algorithm
We need to generate table V(1,…,n, 0,…,W)

Where n = number of objects and W = capacity of knapsack

To generate table V[i][j] use following steps:

1. Make V[i][j] = 0 for 0 < I <= n and V[0][j] = 0

2. If j < wi then

V[i][j] = V[i-1][j]

3. If j >= wi then

V[i][j] = max(V[i-1][j], V[i-1][j-wi] + vi)

 Program
#include <stdio.h>

int max(int a, int b) { return (a > b) ? a : b; }


Page 27
TY IT 2 B 190410116114

int knapSack(int W, int wt[], int val[], int n)

if (n == 0 || W == 0)

return 0;

if (wt[n - 1] > W)

return knapSack(W, wt, val, n - 1);

else

return max(

val[n - 1] + knapSack(W - wt[n - 1], wt, val, n - 1),

knapSack(W, wt, val, n - 1));

int main()

int val[] = {10, 40, 30, 50 };

int wt[] = { 5, 4, 6, 3 };

int W = 10;

int n = sizeof(val) / sizeof(val[0]);


printf("Profit is %d", knapSack(W, wt, val, n));

return 0;

Page 28
TY IT 2 B 190410116114

 Output:

 Time Complexity
Time Complexity: O(2^n)

Page 29
TY IT 2 B 190410116114

PRACTICAL 6
Aim: Implementation of Chain Matrix Multiplication Using Dynamic
Programming.
A. Chain Matrix Multiplication
 Description
 Given a sequence of matrices, find the most efficient way to multiply
these matrices together.
 The problem is not actually to perform the multiplications, but merely to
decide in which order to perform the multiplications.
 We have many options to multiply a chain of matrices because matrix
multiplication is associative.
 In other words, no matter how we parenthesize the product, the result
will be the same. For example, if we had four matrices A, B, C, and D, we
would have: 
(ABC)D = (AB)(CD) = A(BCD) = ....

 Algorithm
Matrix Table M[i][j] stores the cost of multiplications.
To generate M[i][j] use the following algorithm:
If i = j then M[i][j] = 0
If j = i + 1 then M[i][j] = Pi-1 . Pi . Pi+1
If i < j then
M[i][j] = min(M[i][k] + M[k+1][j] + Pi-1 . Pk . Pj) with i <= k < j

 Program

#include<stdio.h>
#include<limits.h>

int MatrixChainMultiplication(int p[], int n)


{
int m[n][n];
int i, j, k, L, q;

for (i=1; i<n; i++)


m[i][i] = 0;

Page 30
TY IT 2 B 190410116114

for (L=2; L<n; L++)


{
for (i=1; i<n-L+1; i++)
{
j = i+L-1;
m[i][j] = INT_MAX;

for (k=i; k<=j-1; k++)


{
q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
if (q < m[i][j])
{
m[i][j] = q;
}
}
}
}

return m[1][n-1];

int main()
{
int n,i;
printf("Enter number of matrices\n");
scanf("%d",&n);

n++;

Page 31
TY IT 2 B 190410116114

int arr[n];

printf("Enter dimensions \n");

for(i=0;i<n;i++)
{
printf("Enter d%d :: ",i);
scanf("%d",&arr[i]);
}

int size = sizeof(arr)/sizeof(arr[0]);

printf("Minimum number of multiplications is %d ",


MatrixChainMultiplication(arr, size));

return 0;
}

Page 32
TY IT 2 B 190410116114

 Output:

 Time Complexity

Time Complexity: O(n3)

Page 33
TY IT 2 B 190410116114

PRACTICAL 7
Aim: Implementation of making a change problem using dynamic
programming.
A. Making a Change Problem
 Description
 There are infinite number of coins of n different values. These
values are given. Using these coins, you have to make change for
Rs. Sum.

 Find the minimum number of coins required to change Rs. Sum.

 Note that the problem is different from coin change problem. In


coin change problem, we were asked to find out in how many ways
the change can be made.

 In this problem, we are supposed to find out the minimum number


of coins required to change.

 Algorithm
We need to generate a table c[n][N], where n = number of denominations,
N = amount for which you need to make a change.

To generate table c[i][j] use following algorithm:

Make c[i][0] = 0 for 0 < i <= n

Repeat the following steps for the remaining matrix values:

If i = 1 then c[i][j] = 1 + c[i][j – d1], here d1 = 1

If j < di then c[i][j] = c[i-1][j]

Otherwise c[i][j] = min(c[i-1][j], 1 + c[i][j – di])

 Program
#include <stdio.h>

#define MIN(x, y) (((x) < (y)) ? (x) : (y))

const int INF = 100000;

int coin_change(int d[], int k, int n) {

int M[n+1];

Page 34
TY IT 2 B 190410116114

M[0] = 0;

int i, j;

for(j=1; j<=n; j++) {

int minimum = INF;

for(i=1; i<=k; i++) {

if(j >= d[i]) {

minimum = MIN(minimum, 1+M[j-d[i]]);

M[j] = minimum;

return M[n];

int main() {

int d[20],n,k,i;

printf("Enter total no of coins i.e. array size: ");

scanf("%d",&k);

printf("Enter change: ");

scanf("%d",&n);

printf("Enter denominations i.e. array elements: ");

for(i=0;i<k;i++)

scanf("%d",&d[i]);

printf("Minimum no of coins required: %d\n", coin_change(d, k, n));

return 0;

Page 35
TY IT 2 B 190410116114

 Output

 Time Complexity
Time Complexity: O(n*k)

Where n = change and k = no. of coins

Page 36
TY IT 2 B 190410116114

PRACTICAL 8
Aim: Implementation of a knapsack problem using greedy algorithm.

A. Fractional Knapsack Problem

 Description

 Given weights and values of n items, we need to put these items in a


knapsack of capacity W to get the maximum total value in the
knapsack.

 In the 0-1 Knapsack problem (dynamic programming), we are not


allowed to break items. We either take the whole item or don’t take it. 

 In Fractional Knapsack, we can break items for maximizing the total


value of knapsack. This problem in which we can break an item is also
called the fractional knapsack problem. 

 Algorithm

Greedy-Fractional-Knapsack (w[1,..,n] , p[1,…,n] , W)

For i = 1 to n do

X[i]  0

weight  0

While weight < W do

I  the best remaining object

If weight + W[i] <= W then

X[i]  1

weight  weight + w[i]

else

x[i]  (W – weight ) / w[i]

Page 37
TY IT 2 B 190410116114

weight  W

return x

 Program

# include<stdio.h>

void knapsack(int n, float weight[], float profit[], float capacity)

float x[20], tp = 0;

int i, j, u;

u = capacity;

for (i = 0; i < n; i++)

x[i] = 0.0;

for (i = 0; i < n; i++)

if (weight[i] > u)

break;

else

{
x[i] = 1.0;

tp = tp + profit[i];

Page 38
TY IT 2 B 190410116114

u = u - weight[i];

if (i < n)

x[i] = u / weight[i];

tp = tp + (x[i] * profit[i]);

printf("\nThe result vector is:- ");

for (i = 0; i < n; i++)

printf("%f\t", x[i]);

printf("\nMaximum profit is:- %f", tp);

int main()

float weight[20], profit[20], capacity;

int num, i, j;

float ratio[20], temp;

Page 39
TY IT 2 B 190410116114

printf("\nEnter the no. of objects:- ");

scanf("%d", &num);

printf("\nEnter the wts and profits of each object:- ");

for (i = 0; i < num; i++)

scanf("%f %f", &weight[i], &profit[i]);

printf("\nEnter the capacity of knapsack:- ");

scanf("%f", &capacity);

for (i = 0; i < num; i++)

ratio[i] = profit[i] / weight[i];

for (i = 0; i < num; i++)

for (j = i + 1; j < num; j++)

if (ratio[i] < ratio[j])

Page 40
TY IT 2 B 190410116114

temp = ratio[j];

ratio[j] = ratio[i];

ratio[i] = temp;

temp = weight[j];

weight[j] = weight[i];

weight[i] = temp;

temp = profit[j];

profit[j] = profit[i];

profit[i] = temp;

knapsack(num, weight, profit, capacity);

return(0);
}

Page 41
TY IT 2 B 190410116114

 Output:

 Time Complexity

Time Complexity: O(nlogn)

Page 42
TY IT 2 B 190410116114

PRACTICAL 9
Aim: Implementation of Graph and Searching (DFS and BFS).
A. Graph and Searching (DFS and BFS)
 Description
 Depth-first search is an algorithm for traversing or searching tree or
graph data structures.
 The algorithm starts at the root node (selecting some arbitrary node as
the root node in the case of a graph) and explores as far as possible along
each branch before backtracking.
 So the basic idea is to start from the root or any arbitrary node and mark
the node and move to the adjacent unmarked node and continue this loop
until there is no unmarked adjacent node.
 Then backtrack and check for other unmarked nodes and traverse them.
Finally print the nodes in the path.
 BFS is a traversing algorithm where you should start traversing from a
selected node (source or starting node) and traverse the graph layerwise
thus exploring the neighbour nodes (nodes which are directly connected
to source node). You must then move towards the next-level neighbour
nodes.

 Algorithm
 Depth First Algorithm (DFS)
procedure dfsearch(G)
   for each v Є N 
    do mark[v] ← not-visited
   for each v Є N 
    do if mark[v] ≠ visited 
       then dfs(v)

procedure dfs(v)
   {Node v has not previously been visited}
   mark[v] ← visited
   for each node w adjacent to v 
    do if mark[w] ≠ visited 
       then dfs(w)

 Breadth First Algorithm (BFS)


procedure bfs(v)
   Q ← empty-queue
   mark[v] ← visited

Page 43
TY IT 2 B 190410116114

   enqueue v into Q
   while Q is not empty 
   do u ← first(Q)
dequeue u from Q
for each node w adjacent to u 
      do if mark[w] ≠ visited 
         then mark[w] ← visited
      enqueue w into Q

procedure search(G)
   for each v Є N 
   do mark[v] ← not visited
   for each v Є N 
   do if mark[v] ≠ visited 
      then bfs(v)

 Program
 Depth First Search (DFS)

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

struct node {
int vertex;
struct node* next;
};

struct node* createNode(int v);

struct Graph {
int numVertices;
int* visited;

struct node** adjLists;


};

Page 44
TY IT 2 B 190410116114

void DFS(struct Graph* graph, int vertex) {


struct node* adjList = graph->adjLists[vertex];
struct node* temp = adjList;

graph->visited[vertex] = 1;
printf("Visited %d \n", vertex);

while (temp != NULL) {


int connectedVertex = temp->vertex;

if (graph->visited[connectedVertex] == 0) {
DFS(graph, connectedVertex);
}
temp = temp->next;
}
}

struct node* createNode(int v) {


struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}

struct Graph* createGraph(int vertices) {


struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;

graph->adjLists = malloc(vertices * sizeof(struct node*));

graph->visited = malloc(vertices * sizeof(int));

Page 45
TY IT 2 B 190410116114

int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}
return graph;
}

void addEdge(struct Graph* graph, int src, int dest) {

struct node* newNode = createNode(dest);


newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;

newNode = createNode(src);
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}

void printGraph(struct Graph* graph) {


int v;
for (v = 0; v < graph->numVertices; v++) {
struct node* temp = graph->adjLists[v];
printf("\n Adjacency list of vertex %d\n ", v);
while (temp) {
printf("%d -> ", temp->vertex);
temp = temp->next;
}
printf("\n");
}
}

Page 46
TY IT 2 B 190410116114

int main() {
struct Graph* graph = createGraph(4);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 2);
addEdge(graph, 2, 3);

printGraph(graph);

DFS(graph, 2);

return 0;
}

 Breadth First Search (BFS)

#include <stdio.h>
#include <stdlib.h>
#define SIZE 40

struct queue {
int items[SIZE];
int front;
int rear;
};

struct queue* createQueue();


void enqueue(struct queue* q, int);
int dequeue(struct queue* q);
void display(struct queue* q);
int isEmpty(struct queue* q);
void printQueue(struct queue* q);

struct node {

Page 47
TY IT 2 B 190410116114

int vertex;
struct node* next;
};

struct node* createNode(int);

struct Graph {
int numVertices;
struct node** adjLists;
int* visited;
};

void bfs(struct Graph* graph, int startVertex) {


struct queue* q = createQueue();

graph->visited[startVertex] = 1;
enqueue(q, startVertex);

while (!isEmpty(q)) {
printQueue(q);
int currentVertex = dequeue(q);
printf("Visited %d\n", currentVertex);

struct node* temp = graph->adjLists[currentVertex];

while (temp) {
int adjVertex = temp->vertex;

if (graph->visited[adjVertex] == 0) {
graph->visited[adjVertex] = 1;
enqueue(q, adjVertex);
}
temp = temp->next;
}

Page 48
TY IT 2 B 190410116114

}
}

struct node* createNode(int v) {


struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}

struct Graph* createGraph(int vertices) {


struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;

graph->adjLists = malloc(vertices * sizeof(struct node*));


graph->visited = malloc(vertices * sizeof(int));

int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}

return graph;
}

void addEdge(struct Graph* graph, int src, int dest) {

struct node* newNode = createNode(dest);


newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;

Page 49
TY IT 2 B 190410116114

newNode = createNode(src);
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}

struct queue* createQueue() {


struct queue* q = malloc(sizeof(struct queue));
q->front = -1;
q->rear = -1;
return q;
}

int isEmpty(struct queue* q) {


if (q->rear == -1)
return 1;
else
return 0;
}

void enqueue(struct queue* q, int value) {


if (q->rear == SIZE - 1)
printf("\nQueue is Full!!");
else {
if (q->front == -1)
q->front = 0;
q->rear++;
q->items[q->rear] = value;
}
}

Page 50
TY IT 2 B 190410116114

int dequeue(struct queue* q) {


int item;
if (isEmpty(q)) {
printf("Queue is empty");
item = -1;
} else {
item = q->items[q->front];
q->front++;
if (q->front > q->rear) {
printf("Resetting queue ");
q->front = q->rear = -1;
}
}
return item;
}

void printQueue(struct queue* q) {


int i = q->front;

if (isEmpty(q)) {
printf("Queue is empty");
} else {
printf("\nQueue contains \n");
for (i = q->front; i < q->rear + 1; i++) {
printf("%d ", q->items[i]);
}
}
}

int main() {
struct Graph* graph = createGraph(6);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);

Page 51
TY IT 2 B 190410116114

addEdge(graph, 1, 2);
addEdge(graph, 1, 4);
addEdge(graph, 1, 3);
addEdge(graph, 2, 4);
addEdge(graph, 3, 4);

bfs(graph, 0);

return 0;
}

 Output:
 Depth First Search (DFS)

Page 52
TY IT 2 B 190410116114

 Breadth First Search (BFS)

 Time Complexity

Time Complexity of DFS Algorithm: O(V + E), where V is the number of vertices
and E is the number of edges in the graph.

Time Complexity of BFS Algorithm: O(V + E), where V is the number of vertices
and E is the number of edges in the graph.

Page 53
TY IT 2 B 190410116114

PRACTICAL 10
Aim: Implement prim’s algorithm.
A. Prim’s Algorithm
 Description
 Prim's Algorithm is used to find the minimum spanning tree from a
graph.

 Prim's algorithm finds the subset of edges that includes every vertex
of the graph such that the sum of the weights of the edges can be
minimized.

 Prim's algorithm starts with the single node and explore all the
adjacent nodes with all the connecting edges at every step.

 The edges with the minimal weights causing no cycles in the graph got
selected.

 Algorithm

Prim's algorithm shows how we create two sets of vertices U and V-U.
U contains the list of vertices that have been visited and V-U the list of
vertices that haven't. One by one, we move vertices from set V-U to set
U by connecting the least weight edge.
T = ∅;
U = { 1 };
while (U ≠ V)
let (u, v) be the lowest cost edge such that u ∈ U and v ∈ V - U;
T = T ∪ {(u, v)}
U = U ∪ {v}
 Program
#include<stdio.h>

#include<stdbool.h>

#include <string.h>

#define INF 9999999

#define V 5

int G[V][V] = {
Page 54
TY IT 2 B 190410116114

{0, 9, 75, 0, 0},

{9, 0, 95, 19, 42},

{75, 95, 0, 51, 66},

{0, 19, 51, 0, 31},

{0, 42, 66, 31, 0}};

int main() {

int no_edge;

int selected[V];

memset(selected, false, sizeof(selected));

no_edge = 0;

selected[0] = true;

int x;

int y;

printf("Edge : Weight\n");

while (no_edge < V - 1) {

int min = INF;

x = 0;

y = 0;

Page 55
TY IT 2 B 190410116114

for (int i = 0; i < V; i++) {

if (selected[i]) {

for (int j = 0; j < V; j++) {

if (!selected[j] && G[i][j]) { // not in selected and there is an edge

if (min > G[i][j]) {

min = G[i][j];

x = i;

y = j;

printf("%d - %d : %d\n", x, y, G[x][y]);

selected[y] = true;

no_edge++;

return 0;

 Output

Page 56
TY IT 2 B 190410116114

 Time Complexity
Time Complexity: O(n2)

Page 57
TY IT 2 B 190410116114

PRACTICAL 11
Aim: Implement kruskal’s algorithm.
A. Kruskal’s Algorithm
 Description
 Kruskal's algorithm initially places all the nodes of the original
graph isolated from each other, to form a forest of single node
trees, and then gradually merges these trees, combining at each
iteration any two of all the trees with some edge of the original
graph.

 Before the execution of the algorithm, all edges are sorted by


weight (in non-decreasing order).

 Then begins the process of unification: pick all edges from the first
to the last (in sorted order), and if the ends of the currently picked
edge belong to different subtrees, these subtrees are combined,
and the edge is added to the answer.

 After iterating through all the edges, all the vertices will belong to
the same sub-tree, and we will get the answer.

 Algorithm
Function Kruskal(G = (N, A))

Sort A by increasing length 

n ← the number of nodes in N

T ← Ø {edges of the minimum spanning tree} 

Define n sets, containing a different element of set N 

repeat

e ← {u, v} //e is the shortest edge not yet considered

ucomp ← find(u) 

vcomp ← find(v) 

if ucomp ≠ vcomp then merge(ucomp, vcomp) 

T ← T U {e} 

until T contains n - 1 edges 

return T

Page 58
TY IT 2 B 190410116114

 Program
#include <stdio.h>

#define MAX 30

typedef struct edge {

int u, v, w;

} edge;

typedef struct edge_list {

edge data[MAX];

int n;

} edge_list;

edge_list elist;

int Graph[MAX][MAX], n;

edge_list spanlist;

void kruskalAlgo();

int find(int belongs[], int vertexno);

void applyUnion(int belongs[], int c1, int c2);

void sort();

void print();

void kruskalAlgo() {

int belongs[MAX], i, j, cno1, cno2;

elist.n = 0;

for (i = 1; i < n; i++)

Page 59
TY IT 2 B 190410116114

for (j = 0; j < i; j++) {

if (Graph[i][j] != 0) {

elist.data[elist.n].u = i;

elist.data[elist.n].v = j;

elist.data[elist.n].w = Graph[i][j];

elist.n++;

sort();

for (i = 0; i < n; i++)

belongs[i] = i;

spanlist.n = 0;

for (i = 0; i < elist.n; i++) {

cno1 = find(belongs, elist.data[i].u);

cno2 = find(belongs, elist.data[i].v);

if (cno1 != cno2) {

spanlist.data[spanlist.n] = elist.data[i];

spanlist.n = spanlist.n + 1;

applyUnion(belongs, cno1, cno2);

int find(int belongs[], int vertexno) {

Page 60
TY IT 2 B 190410116114

return (belongs[vertexno]);

void applyUnion(int belongs[], int c1, int c2) {

int i;

for (i = 0; i < n; i++)

if (belongs[i] == c2)

belongs[i] = c1;

void sort() {

int i, j;

edge temp;

for (i = 1; i < elist.n; i++)

for (j = 0; j < elist.n - 1; j++)

if (elist.data[j].w > elist.data[j + 1].w) {

temp = elist.data[j];

elist.data[j] = elist.data[j + 1];

elist.data[j + 1] = temp;

void print() {

int i, cost = 0;

for (i = 0; i < spanlist.n; i++) {

Page 61
TY IT 2 B 190410116114

printf("\n%d - %d : %d", spanlist.data[i].u, spanlist.data[i].v,


spanlist.data[i].w);

cost = cost + spanlist.data[i].w;

printf("\nSpanning tree cost: %d", cost);

int main() {

int i, j, total_cost;

n = 6;

Graph[0][0] = 0;

Graph[0][1] = 4;

Graph[0][2] = 4;

Graph[0][3] = 0;

Graph[0][4] = 0;

Graph[0][5] = 0;

Graph[0][6] = 0;

Graph[1][0] = 4;

Graph[1][1] = 0;

Graph[1][2] = 2;

Graph[1][3] = 0;

Graph[1][4] = 0;

Graph[1][5] = 0;

Graph[1][6] = 0;

Page 62
TY IT 2 B 190410116114

Graph[2][0] = 4;

Graph[2][1] = 2;

Graph[2][2] = 0;

Graph[2][3] = 3;

Graph[2][4] = 4;

Graph[2][5] = 0;

Graph[2][6] = 0;

Graph[3][0] = 0;

Graph[3][1] = 0;

Graph[3][2] = 3;

Graph[3][3] = 0;

Graph[3][4] = 3;

Graph[3][5] = 0;

Graph[3][6] = 0;

Graph[4][0] = 0;

Graph[4][1] = 0;

Graph[4][2] = 4;

Graph[4][3] = 3;

Graph[4][4] = 0;

Graph[4][5] = 0;

Graph[4][6] = 0;

Graph[5][0] = 0;

Graph[5][1] = 0;

Graph[5][2] = 2;

Graph[5][3] = 0;

Graph[5][4] = 3;

Page 63
TY IT 2 B 190410116114

Graph[5][5] = 0;

Graph[5][6] = 0;

kruskalAlgo();

print();

 Output

 Time Complexity
Time Complexity: O(ElogE)

Page 64
TY IT 2 B 190410116114

PRACTICAL 12
Aim: Implementation of LCS Problem.
A. LCS Problem
 Description
 A subsequence of a given sequence is just the given sequence with some
elements left out.

 Given two sequences X and Y, we say that the sequence Z is a common


sequence of X and Y if Z is a subsequence of both X and Y.

 In the longest common subsequence problem, we are given two


sequences X = (x1 x2....xm) and Y = (y1 y2 yn) and wish to find a maximum
length common subsequence of X and Y. LCS Problem can be solved using
dynamic programming.

 Algorithm
X and Y be two given sequences

Initialize a table LCS of dimension X.length * Y.length

X.label = X

Y.label = Y

LCS[0][] = 0

LCS[][0] = 0

Start from LCS[1][1]


Compare X[i] and Y[j]

If X[i] = Y[j]

LCS[i][j] = 1 + LCS[i-1, j-1]

Point an arrow to LCS[i][j]

Else

LCS[i][j] = max(LCS[i-1][j], LCS[i][j-1])

Point an arrow to max(LCS[i-1][j], LCS[i][j-1])

 Program

Page 65
TY IT 2 B 190410116114

#include <stdio.h>

#include <string.h>

int i, j, m, n, LCS_table[20][20];

char S1[20] = "ABCBDAB", S2[20] = "BDCABA", b[20][20];

void lcsAlgo() {

m = strlen(S1);

n = strlen(S2);

for (i = 0; i <= m; i++)

LCS_table[i][0] = 0;

for (i = 0; i <= n; i++)

LCS_table[0][i] = 0;

for (i = 1; i <= m; i++)

for (j = 1; j <= n; j++) {

if (S1[i - 1] == S2[j - 1]) {


LCS_table[i][j] = LCS_table[i - 1][j - 1] + 1;

} else if (LCS_table[i - 1][j] >= LCS_table[i][j - 1]) {

LCS_table[i][j] = LCS_table[i - 1][j];

} else {

LCS_table[i][j] = LCS_table[i][j - 1];

Page 66
TY IT 2 B 190410116114

int index = LCS_table[m][n];

char lcsAlgo[index + 1];

lcsAlgo[index] = '\0';

int i = m, j = n;

while (i > 0 && j > 0) {

if (S1[i - 1] == S2[j - 1]) {

lcsAlgo[index - 1] = S1[i - 1];

i--;

j--;

index--;

else if (LCS_table[i - 1][j] > LCS_table[i][j - 1])

i--;

else

j--;

}
printf("S1 : %s \nS2 : %s \n", S1, S2);

printf("LCS: %s", lcsAlgo);

int main() {

lcsAlgo();

printf("\n");

 Output

Page 67
TY IT 2 B 190410116114

 Time Complexity
Time Complexity: O(2n)

Page 68

You might also like