You are on page 1of 24

Design and Analysis of Algorithms Lab

Practical Report (IT105402IT)

Name: Anirudha Shivarkar


Roll No.: 19118901
Semester: 5th
Branch: Information Technology

Submitted to: Dr. Govind P. Gupta

1
1. Write a program for Building the Max heap and then sort the given
elements using Heap sort and show the result by using different test-cases
with appropriate input data.
Ans:
Building Max heap and using Heap sort:
A Binary Heap is a heap where each node can have at most two children. A
heap is a complete binary tree. In a Max-Heap, the maximum element is always
present at the root node which is the first element in the array used to represent
the Heap. The idea is to heapify the complete binary tree formed from the array
in reverse level order following top-down approach.
Time complexity: O (n). where n is number of elements.
Heap sort is a comparison based sorting technique based on Binary Heap data
structure. It is similar to selection sort where we first find the maximum element
and place the maximum element at the end. We repeat the same process for
remaining elements.
Steps:

1. Build a max heap from the input data.


2. At this point, the largest item is stored at the root of the heap. Replace it
with the last item of the heap followed by reducing the size of heap by 1.
Finally, heapify the root of tree.
3. Repeat above steps while size of heap is greater than 1.

Time complexity: O(N*LogN) where N is the number of elements in the array.

1. // Program to build a Max Heap and perform Heap Sort.


2.
3. #include <iostream>
4. using namespace std;
5.
6. void MaxHeapify(int arr[], int n, int i)
7. { int largest = i;
8. int l = 2 * i + 1;
9. int r = 2 * i + 2;
10.
11. if (l < n && arr[l] > arr[largest])
12. largest = l;
13.
14. if (r < n && arr[r] > arr[largest])
15. largest = r;
16.
17. if (largest != i) {
18. swap(arr[i], arr[largest]);

2
19.
20. MaxHeapify(arr, n, largest);
21. }
22. }
23.
24. void buildHeap(int arr[], int n)
25. {
26. int startIdx = (n / 2) - 1;
27.
28. for (int i = startIdx; i >= 0; i--) {
29. MaxHeapify(arr, n, i);
30. }
31. }
32. void heapSort(int arr[], int n)
33. {
34. for (int i = n - 1; i > 0; i--) {
35. swap(arr[0], arr[i]);
36. MaxHeapify(arr, i, 0);
37. }
38. }
39.
40. int main()
41. { int testcases;
42. cout << "Enter no. of testcases: ";
43. cin >> testcases;
44. while(testcases--){
45.
46. cout << "Enter array size: ";
47. int n;
48. cin >> n;
49.
50. int arr[n];
51.
52. cout << "Enter the array: ";
53. for(int i = 0; i < n; i++){
54. cin >> arr[i];
55. }
56.
57. buildHeap(arr, n);
58. cout << "Array representation of Heap is:\n";
59.
60. for (int i = 0; i < n; ++i)
61. cout << arr[i] << " ";
62. cout << "\n";
63. heapSort(arr, n);
64.
65. cout << "Array after Heap Sort is:\n";
66.
67. for(int i = 0; i < n; i++)
68. cout << arr[i] << " ";
69.
70. cout << "\n";
71. }
72.
73. return 0;
74. }
75.

3
OUTPUT:

4
2. Write a program for finding the kth minimum and maximum element in
a Max-Heap and test it with appropriate input data.
Ans: Max-Heap kth maximum and kth minimum:
Kth maximum and Kth minimum can be found using Binary heap. Max Heap
has property that maximum element can be extracted in O (1) time. This
property can be used until Kth maximum and kth minimum elements are
obtained.

1. #include <bits/stdc++.h>
2. using namespace std;
3. int parent(int i)
4. {
5. return (i-1)/2;
6. }
7. int left(int i)
8. {
9. return (i*2)+1;
10. }
11. int right(int i)
12. {
13. return (i*2)+2;
14. }
15. void swap(int *a,int *b)
16. {
17. int temp = *a;
18. *a = *b;
19. *b = temp;
20. }
21.
22. void MaxHeapify(int arr[], int n, int i)
23. { int largest = i;
24. int l = 2 * i + 1;
25. int r = 2 * i + 2;
26.
27. if (l < n && arr[l] > arr[largest])
28. largest = l;
29.
30. if (r < n && arr[r] > arr[largest])
31. largest = r;
32.
33. if (largest != i) {
34. swap(arr[i], arr[largest]);
35.
36. MaxHeapify(arr, n, largest);
37. }
38. }
39.
40. int extract(int heap[],int *size)
41. {
42. int root = heap[0];
43. heap[0] = heap[*size-1];
44. (*size)--;
45. MaxHeapify(heap,*size, 0);
46. return root;
47. }
48.
49. void buildHeap(int arr[], int n)
50. {
51. int startIdx = (n / 2) - 1;
52.
53. for (int i = startIdx; i >= 0; i--) {

5
54. MaxHeapify(arr, n, i);
55. }
56. }
57.
58.
59. int main()
60. {
61. int t;
62. cout << "Enter no. of testcases:";
63. cin>>t;
64. while(t--)
65. {
66. int n,k;
67. cout << "Enter no. of elements: ";
68. cin>>n;
69. cout << "Enter K: ";
70. cin >> k;
71. int *heap = new int [n];
72. int size = n;
73. cout << "Enter array elements: ";
74. for(int i=0;i<n;i++)
75. {
76. int t;
77. cin>>t;
78. heap[i] = t;
79. }
80. buildHeap(heap, n);
81. for(int i = 0; i < n; i++){
82. cout << heap[i] << " ";
83. }
84. cout << "\n";
85.
86. int t = 0;
87. bool flag1 = false, flag2 = false;
88. while(true)
89. {
90. int temp = extract(heap, &size);
91. t++;
92. if(t == (k)) { cout << "Kth Largest: " << temp << endl; flag1 =
true;}
93. if( t == (n - k + 1)){ cout << "Kth Smallest: " << temp << endl;
flag2 = true;}
94. if(flag1 and flag2) break;
95.
96. }
97.
98. }
99. return 0;
100. }
101.

6
OUTPUT:

7
3. Write a program to implement Quick Sort using first/last/any random
element as pivot and test it with appropriate list of input data.
Ans.
QuickSort is a Divide and Conquer algorithm. It picks an element as pivot and
partitions the given array around the picked pivot. There are many different
versions of quickSort that pick pivot in different ways.

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.

For the partition algorithm, the logic is simple, we start from the leftmost
element and keep track of index of smaller (or equal to) elements as i. While
traversing, if we find a smaller element, we swap current element with arr[i].
Otherwise we ignore current element.

Average case time complexity: O (n Logn)


Worst case time complexity: O (n2)
QuickSort is faster in practice, because its inner loop can be efficiently
implemented on most architectures, and in most real-world data.

a. Quick Sort using last element as pivot:

1.
2. #include <iostream>
3. using namespace std;
4.
5.
6. int Partition(int arr[], int l, int h)
7. {
8. int pivot=arr[h];
9. int i=l-1;
10. for(int j=l;j<=h-1;j++){
11. if(arr[j]<pivot){
12. i++;
13. swap(arr[i],arr[j]);
14. }
15. }
16. swap(arr[i+1],arr[h]);
17. return i+1;
18. }
19.
20. void qSort(int arr[],int l,int h){
21. if(l<h){
22. int p= Partition(arr,l,h);
23. qSort(arr,l,p-1);
24. qSort(arr,p+1,h);
25. }

8
26. }
27.
28.
29.
30. int main(){
31. int t;
32. cout << "Enter no. of testcases: ";
33. cin >> t;
34.
35. while(t--){
36.
37. cout << "Enter array size: ";
38. int n;
39. cin >> n;
40.
41. cout << "Enter array elements: ";
42. int arr[n];
43. for(auto &x: arr) cin >> x;
44.
45. qSort(arr, 0, n - 1);
46.
47. cout << "Array after quicksort using last element as pivot is : ";
48.
49. for(int i = 0; i < n; i++){
50. cout << arr[i] << " ";
51. }
52. cout << "\n";
53. }
54. return 0;
55. }
56.
57.

OUTPUT:

9
b. Quick Sort using first element as pivot:

1. #include <iostream>
2. using namespace std;
3.
4.
5. int Partition(int arr[], int l, int h)
6. { swap(arr[l], arr[h]);
7. int pivot=arr[h];
8. int i=l-1;
9. for(int j=l;j<=h-1;j++){
10. if(arr[j]<pivot){
11. i++;
12. swap(arr[i],arr[j]);
13. }
14. }
15. swap(arr[i+1],arr[h]);
16. return i+1;
17. }
18.
19. void qSort(int arr[],int l,int h){
20. if(l<h){
21. int p= Partition(arr,l,h);
22. qSort(arr,l,p-1);
23. qSort(arr,p+1,h);
24. }
25. }
26.
27.
28.
29. int main(){
30. int t;
31. cout << "Enter no. of testcases: ";
32. cin >> t;
33.
34. while(t--){
35.
36. cout << "Enter array size: ";
37. int n;
38. cin >> n;
39.
40. cout << "Enter array elements: ";
41. int arr[n];
42. for(auto &x: arr) cin >> x;
43.
44. qSort(arr, 0, n - 1);
45.
46. cout << "Array after quicksort using first element as pivot is : ";
47.
48. for(int i = 0; i < n; i++){
49. cout << arr[i] << " ";
50. }
51. cout << "\n";
52. }
53. return 0;
54. }
55.

10
OUTPUT:

c. Quick Sort using random pivot:

1. #include <cstdlib>
2. #include <time.h>
3. #include <iostream>
4. using namespace std;
5.
6.
7. int Partition(int arr[], int l, int h)
8. { swap(arr[l], arr[h]);
9. int pivot=arr[h];
10. int i=l-1;
11. for(int j=l;j<=h-1;j++){
12. if(arr[j]<pivot){
13. i++;
14. swap(arr[i],arr[j]);
15. }
16. }
17. swap(arr[i+1],arr[h]);
18. return i+1;
19. }
20.
21. int randomPartition(int arr[], int low, int high)
22. {
23. srand(time(NULL));
24. int random = low + rand() % (high - low);
25.
26. swap(arr[random], arr[high]);
27.
28. return Partition(arr, low, high);
29. }
30.
31. void qSort(int arr[],int l,int h){
32. if(l<h){
33. int p= randomPartition(arr,l,h);
34. qSort(arr,l,p-1);
35. qSort(arr,p+1,h);
36. }
37. }
38.
39.
40.
41. int main(){
42. int t;
43. cout << "Enter no. of testcases: ";
44. cin >> t;
45.
46. while(t--){
47.

11
48. cout << "Enter array size: ";
49. int n;
50. cin >> n;
51.
52. cout << "Enter array elements: ";
53. int arr[n];
54. for(auto &x: arr) cin >> x;
55.
56. qSort(arr, 0, n - 1);
57.
58. cout << "Array after quicksort using random element as pivot is : ";
59.
60. for(int i = 0; i < n; i++){
61. cout << arr[i] << " ";
62. }
63. cout << "\n";
64. }
65.
66. return 0;
67. }
68.

OUTPUT:

12
4. Write a program to implement Counting sort and test it with appropriate
list of input data.
Ans.
Counting sort is a sorting technique based on keys between a specific range. It
works by counting the number of objects having distinct key values (kind of
hashing). Then doing some arithmetic to calculate the position of each object in
the output sequence.
It is not a comparison based sorting. It's running time complexity is O(n) with
space proportional to the range of data.
Time Complexity: O(N + K) where N is the number of elements in input array
and K is the range of input.
Auxiliary Space: O(N + K)
Code for counting sort:

1. #include<bits/stdc++.h>
2. using namespace std;
3.
4. void countSort(int arr[], int n, int k)
5. {
6. int count[k];
7. for(int i=0;i<k;i++)
8. count[i]=0;
9. for(int i=0;i<n;i++)
10. count[arr[i]]++;
11.
12. for(int i=1;i<k;i++)
13. count[i]=count[i-1]+count[i];
14.
15. int output[n];
16. for(int i=n-1;i>=0;i--){
17. output[count[arr[i]]-1]=arr[i];
18. count[arr[i]]--;
19. }
20. for(int i=0;i<n;i++)
21. arr[i]=output[i];
22.
23. }
24.
25. int main()
26. {
27. cout << "Enter no. of testcases: ";
28. int t;
29. cin >> t;
30.
31. int n;
32. cout << "Enter the number of array elements: ";
33. cin >> n;
34.
35. int arr[n];
36. cout << "Enter the array: ";
37. for(auto &x: arr) cin >> x;
38.
39. int k;
40. cout << "Enter the range of numbers: ";
41. cin >> k;
42.

13
43. countSort(arr, n, k);
44.
45.
46. cout << "Array after sorting: ";
47. for (int i = 0; i < n; i++)
48. cout << arr[i] << " ";
49.
50. return 0;
51. }
52.
53.
54.
55.
56.

OUTPUT:

14
6. Write a program to implement the rod-cutting problem using top-down
with memorization technique and show the result by using different test-
cases with appropriate input data.
Ans:
Problem Statement:
Given a rod of length n inches and an array of prices that includes prices of all
pieces of size smaller than n. Determine the maximum value obtainable by
cutting up the rod and selling the pieces.
Rod Cutting problem using memoization (top down) technique:

1. #include <bits/stdc++.h>
2. using namespace std;
3.
4.
5. int MaxTotalPrice(int prices[], vector<vector<int>> &maxPrice, int index,
int sum, vector<int> &rodSize){
6.
7. // Base cases
8. if(index == 0) return 0;
9. if(sum == 0) return 0;
10.
11. if(maxPrice[index][sum] != -1) return maxPrice[index][sum];
12.
13. if(rodSize[index - 1] <= sum) {
14. maxPrice[index][sum] = max(prices[index - 1] + MaxTotalPrice(prices,
maxPrice, index, sum - rodSize[index - 1], rodSize),
15. MaxTotalPrice(prices, maxPrice, index - 1, sum, rodSize));
16. }
17. else{
18. maxPrice[index][sum] = MaxTotalPrice(prices, maxPrice, index - 1, sum,
rodSize);
19. }
20. return maxPrice[index][sum];
21. }
22.
23.
24. int main(){
25.
26. int t;
27. cout << "Enter no of testcases: ";
28. cin >> t;
29.
30. while(t--){
31. int n;
32. cout << "Enter the rod length: ";
33. cin >> n;
34.
35. int prices[n];
36. cout << "Enter the price array: ";
37. for(auto &price: prices) cin >> price;
38.
39. vector<int> rodSize(n);
40. for(int i = 0; i < n; i++) rodSize[i] = i + 1;
41.
42. //DP Matrix
43. vector<vector<int>> maxPrice(n + 1, vector<int> (n + 1, -1));

15
44.
45. cout << "The maximum obtainable price is: ";
46. cout << MaxTotalPrice(prices, maxPrice, n, n, rodSize) << endl;
47.
48. }
49. }
50.

OUTPUT:

16
7. Write a program to implement the matrix chain multiplication problem
and show the result by using different test-cases with appropriate input
data.

Ans:
Problem Statement:
Given a sequence of matrices, find the most efficient way to multiply these
matrices together.

Matrix Multiplication using memoization:

1. #include <bits/stdc++.h>
2. using namespace std;
3.
4. int MatrixChainMul(int n, int dimensions[], vector<vector<int>> &leastMul,
int startIdx, int endIdx){
5. if(startIdx + 1 == endIdx)return 0;
6.
7. if(leastMul[startIdx][endIdx] != -1){
8. return leastMul[startIdx][endIdx];
9. }
10. leastMul[startIdx][endIdx] = INT_MAX;
11. for(int k = startIdx + 1; k < endIdx; k++){
12. leastMul[startIdx][endIdx] = min(leastMul[startIdx][endIdx],
13. MatrixChainMul(n, dimensions, leastMul, startIdx, k)
14. + MatrixChainMul(n, dimensions, leastMul, k, endIdx)
15. + dimensions[startIdx] * dimensions[k] * dimensions[endIdx]);
16. }
17.
18. return leastMul[startIdx][endIdx];
19. }
20.
21.
22.
23. int main(){
24.
25. int t;
26. cout << "Enter number of testcases: ";
27. cin >> t;
28. while(t--){
29. int n;
30. cout << "Enter size of dimension array: ";
31. cin >> n;
32.
33. int dimensions[n];
34.
35. cout << "Enter the dimension array: ";
36. for(auto &d: dimensions) cin >> d;
37.
38. int startIdx = 0, endIdx = n - 1;
39. vector<vector<int>> leastMul(n, vector<int>(n, -1));
40.
41. cout << "Least number of multiplications: ";
42. cout << MatrixChainMul(n, dimensions, leastMul, startIdx, endIdx) << endl;
43. }

17
44. }
45.

OUTPUT:

18
8. Write a program to implement the fractional- Knapsack problem using
Greedy approach and show the result by using different test-cases with
appropriate input data.

Ans:
Problem Statement:
Given a list of elements with specific values and weights associated with them,
the task is to fill a Knapsack of weight W using these elements such that the
value of knapsack is maximum possible.

Fractional Knapsack using Greedy algorithm:

The local optimal strategy is to choose the item that has maximum value vs
weight ratio. This strategy also leads to global optimal solution because we are
allowed to take fractions of an item.

1. #include<bits/stdc++.h>
2. using namespace std;
3.
4. double FracKnapsack(vector<pair <int, int>> &items, int n, int w)
5. {
6. sort(items.begin(), items.end(), [](pair<int, int> &a,
pair<int,int> &b){
7.
8. double r1 = (double)a.first / a.second;
9. double r2 = (double)b.first / b.second;
10. return r1 > r2;
11.
12. });
13.
14. double res = 0.0;
15.
16. for(int i = 0; i < n; i++)
17. {
18. if(items[i].second <= w)
19. {
20. res += items[i].first;
21. w = w - items[i].second;
22. }
23. else
24. {
25. res += items[i].first * ((double) w / items[i].second);
26. break;
27. }
28. }
29.
30.
31. return res;
32. }
33.
34.

19
35.
36.
37.
38. int main(){
39.
40. int t;
41. cout << "Enter number of testcases: ";
42. cin >> t;
43.
44. while(t--){
45. int n;
46. cout << "Enter no of elements: ";
47. cin >> n;
48.
49. vector<int> weight(n), value(n);
50.
51. cout << "Enter weight array: ";
52. for(auto &w: weight) cin >> w;
53.
54. cout << "Enter value array: ";
55. for(auto &v: value) cin >> v;
56.
57. int w;
58. cout << "Enter knapsack capacity: ";
59. cin >> w;
60.
61. vector<pair<int, int>> items;
62.
63. for(int i = 0; i < n; i++){
64. items.push_back({ value[i], weight[i] });
65. }
66.
67. cout << "Maximum value in knapsack: ";
68. cout << FracKnapsack(items, n, w) << endl;
69. }
70. }
71.
72.

OUTPUT:

20
9. Write a program to implement Dijkstra's shortest path algorithm. For a
given vertex in a weighted connected graph, show the result by using
different test-cases.

Ans:
Dijkstra's algorithm is a single source shortest path algorithm and variation of
the BFS algorithm. In Dijkstra's Algorithm, a SPT(shortest path tree) is
generated with given source as root. Each node at this SPT stores the value of
the shortest path from the source vertex to the current vertex. We maintain two
sets, one set contains vertices included in shortest path tree, other set includes
vertices not yet included in shortest path tree. At every step of the algorithm, we
find a vertex which is in the other set (set of not yet included) and has a
minimum distance from the source.
Time complexity: O (V2) where V is no of vertices.

Dijkstra algorithm using adjacency matrix:

1. #include<bits/stdc++.h>
2. using namespace std;
3.
4. vector<int> djikstra(vector<vector<int>> &graph,int src, int V)
5. {
6.
7. vector<int> dist(V,INT_MAX);
8. dist[src]=0;
9. vector<bool> fin(V,false);
10.
11. for (int count = 0; count < V-1 ; count++)
12. {
13. int u = -1;
14.
15. for(int i=0;i<V;i++)
16. if(!fin[i]&&(u==-1||dist[i]<dist[u]))
17. u=i;
18. fin[u] = true;
19.
20. for (int v = 0; v < V; v++)
21.
22. if (graph[u][v]!=0 && fin[v] == false)
23. dist[v] =
min(dist[v],dist[u]+graph[u][v]);
24. }
25. return dist;
26. }
27.
28. int main(){
29.
30. int t;
31. cout << "Enter no of testcases: ";
32. cin >> t;
33.
34. while(t--){

21
35.
36. int n;
37. cout << "Enter the number of vertices: ";
38. cin >> n;
39.
40.
41. vector<vector<int>> graph(n, vector<int>(n));
42.
43. cout << "Enter the adjacency matrix: ";
44. for(int i = 0;i < n; i++){
45. for(int j = 0; j < n; j++){
46. cin >> graph[i][j];
47. }
48. }
49. int src;
50. cout << "Enter the source vertex: ";
51. cin >> src;
52. vector<int> res = djikstra(graph, src, n);
53.
54. cout << "The shortest distance for each vertex from the source
is: ";
55. for(auto &x: res) cout << x << " ";
56. cout << endl;
57.
58. }
59. }
60.
61.
62.
63.

OUTPUT:

22
10. Write a program to implement Minimum Cost Spanning Tree problem.
For a given weighted connected graph, show the result by using different
test-cases.
Ans:

A minimum spanning tree (MST) for a weighted connected graph is a spanning


tree with weight less than or equal to the weight of every other spanning tree.
The weight of a spanning tree is the sum of weights given to each edge of the
spanning tree.
A minimum spanning tree has (V – 1) edges where V is the number of vertices
in the given graph.
Prim’s algorithm is a Greedy algorithm that determines the minimum spanning
tree.

Minimum cost spanning tree using Prim’s algorithm:


1. #include<bits/stdc++.h>
2. using namespace std;
3.
4.
5.
6. int PrimsMST(vector<vector<int>> &graph, int V)
7.
8. {
9. int key[V];int res=0;
10. fill(key,key+V,INT_MAX);
11. vector <bool> mSet(V, false); key[0]=0;
12.
13. for (int cnt = 0; cnt < V ; cnt++)
14. {
15. int u = -1;
16.
17. for(int i=0;i<V;i++){
18. if(!mSet[i]&&(u==-1||key[i]<key[u])){
19. u=i;
20. }
21. }
22.
23. mSet[u] = true;
24. res+=key[u];
25.
26.
27. for (int v = 0; v < V; v++){
28.
29. if (graph[u][v]!=0 && mSet[v] == false){
30. key[v] = min(key[v],graph[u][v]);
31. }
32. }
33. }
34.
35. return res;
36. }

23
37.
38. int main(){
39.
40. int t;
41. cout << "Enter no of testcases: ";
42. cin >> t;
43.
44. while(t--){
45.
46. int n;
47. cout << "Enter the number of vertices: ";
48. cin >> n;
49.
50.
51. vector<vector<int>> graph(n, vector<int>(n));
52.
53. cout << "Enter the adjacency matrix: \n";
54. for(int i = 0;i < n; i++){
55. for(int j = 0; j < n; j++){
56. cin >> graph[i][j];
57. }
58. }
59.
60. cout << "The MST value is: ";
61. cout << PrimsMST(graph, n) << endl;
62.
63. }
64. return 0;
65. }
66.
67.
68.
69.

OUTPUT:

24

You might also like