Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
38 views

Assignment 1

Selection sort is an in-place comparison sorting algorithm with O(n^2) time complexity. The code implements selection sort by finding the minimum element in each iteration and swapping it with the first unsorted element. It runs selection sort on three arrays of different sizes and calculates the average time taken for best, average and worst cases over 10 trials each. The results show that selection sort performs best on pre-sorted or nearly sorted data and worst on reverse sorted data, as expected due to its O(n^2) complexity.

Uploaded by

Sania Aimen
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
38 views

Assignment 1

Selection sort is an in-place comparison sorting algorithm with O(n^2) time complexity. The code implements selection sort by finding the minimum element in each iteration and swapping it with the first unsorted element. It runs selection sort on three arrays of different sizes and calculates the average time taken for best, average and worst cases over 10 trials each. The results show that selection sort performs best on pre-sorted or nearly sorted data and worst on reverse sorted data, as expected due to its O(n^2) complexity.

Uploaded by

Sania Aimen
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 18

Kinnaird College for Women, Lahore

Design and Analysis of Algorithms


Pre-Mid Assignment 1
Instructor: Ms. Rida Hijab
Submitted By: Sania Aimen – F21BSCS051
Submission Date: 20th Feb, 2023
Q1. Against each category listed below, name and describe (in your own words) a class
of problems from CS, for instance, we know that searching through a random list is a
linear time operation.

1. lg n
In the class sorting problems, many sorting algorithms have the lg n time complexity.
 Like a binary search algorithm that divides the sorted input data into separate
halves in each iteration. Since the search space is halved at each iteration, it only
takes log base 2 to the n iterations to complete the search, where n is the size of
the array.
2. Sqrt n
Sqrt n time complexity means that if the input size is n then there are approximately sqrt n
basic operations, in the case of sorting algorithms comparisons.
 For instance, finding the kth smallest element in an unsorted array. The basic idea
is to divide the array into blocks of size sqrt n and then find the median.
 Another problem is of the range queries in a one-dimensional array or database
queries etc.
3. N
n is used for the time complexity in which we have to traverse the whole array or list of
input values. It depends on the size of the input.
 In searching algorithms to find the key element a linear search is conducted that
takes O(n) time complexity.
 Traversing through a linked list also takes O(n) time
 Finding the min and max elements in an array requires iterating through each
element
 Also in sorting algorithms it takes n comparisons to sort the array, hence taking
O(n) time to be sorted.
4. N lg N
O(n lg n) time complexity means that the lg n operations will occur n times. It is
associated with divide-and-conquer algorithms. They work by dividing the problem into
smaller sub-problems, solving the sub-problems recursively, and then combining the
solutions and the sub-problems to find the answer.
 Merge sort: recursively divides the array into halves and at the end combines the
sorted halves into one sorted array.
 Quick sort: Selects a pivot point and divide the array on the basis of less and
greater than the pivot.
 Heapsort: Finds the key element and puts it at the end of the array.
The above mentioned divide and conquer algorithms all have O(n lg n) time complexity
5. N^2
The class of computer science problems associated that has the time complexity of n^2
are usually related to the algorithms that use nested loops. These algorithms work on pair
of elements, which results in the number of operations increasing quadratically with the
input size.
 Bubble sort: Compares the pair of elements and moves the largest element at the
end of the array
 Inserting sort: Sorts the elements as they are inserted into their proper place in the
array
 Selection sort: Sorts repeatedly by selecting the smallest element and swapping
with the first sorted element the array
 Shorted paths: shortest paths algorithms find the path using the nested loop
approach.
All of the above mentioned problems have O(n^2) time complexity.
6. N^3
When the algorithm runs over 3 nested loops then the algorithm is said to have cubic time
complexity.
Here are some CS related problems that have cubic time complexity:
 Matrix multiplication: Computing the product of two n x n matrices and the
resulting matrix is the sum of n products.
 Determinant of a matrix: Calculating the determinant of the matrix is done by
using b cofactor expansion and takes n^3 time.
 Calculating the inverse of a matrix: reducing the matrix by Gaussian elimination
and then applying back substituting
All these problems have n^3 time complexity.
7. 2^n
2^n time complexity is associated with the exponential growth of the algorithm
depending on the input size n and is observed in recursive algorithms.
Following are some problems that exhibit the time complexity of 2^n:
 Recursive algorithms that perform a task recursively until they reach the base case.
 Generating all subsets of a set requires evaluating 2^n possible subsets.
8. N! (Factorial time)
The n! time complexity is associated with problems involving calculating permutations
and combinations of a given set of items.
Some examples of algorithms have O(n!) time complexity is:
 Traveling salesman problem: It finds all the permutations of the cities to find the
shortest route.
 Generating subsets of a set: All possible ways to find k items from a set of n
elements
Q2.
 Selection sort
Code:
#include <iostream>
#include <chrono>
using namespace std;

// Selection sort in C++

#include <iostream>
using namespace std;

// function to swap the the position of two elements


void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}

void selection_sort(int array[], int size) {


for (int step = 0; step < size - 1; step++) {
int min_idx = step;
for (int i = step + 1; i < size; i++) {

// To sort in descending order, change > to < in this line.


// Select the minimum element in each loop.
if (array[i] < array[min_idx])
min_idx = i;
}
// put min at the correct position
swap(&array[min_idx], &array[step]);
}
}

int main(){
int arr1[50] = {5, 15, 37, 42, 47, 146, 165, 168, 171, 177, 192, 216, 218, 221, 237, 282,
296, 343,
425, 429, 439, 484, 485, 491, 513, 514, 519, 522, 535, 546, 574, 594, 600, 690, 701, 730,
743, 755,
770, 794, 795, 810, 815, 828, 849, 866, 876, 884, 918, 946};

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

int trials = 10;


double total_time = 0;

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


auto start = chrono::high_resolution_clock::now();
selection_sort(arr1, n);
auto end = chrono::high_resolution_clock::now();
double time_taken = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken / 1e9 << " seconds" <<
endl;
total_time += time_taken;
}
cout<<endl;
double avg_time = total_time / trials;
cout << "Average time taken for best case " << trials << " trials: " << avg_time / 1e9 << "
seconds" << endl;
cout<<endl;
int arr2[150] = {91, 81, 127, 92, 61, 123, 50, 118, 39, 146, 93, 104, 31, 145, 125, 71, 35, 6,
67, 43, 23,
58, 80, 135, 40, 34, 105, 70, 137, 126, 77, 14, 100, 113, 107, 56, 111, 2, 133, 149, 30, 49,
132, 147,
76, 117, 116, 16, 144, 143, 26, 112, 1, 51, 139, 87, 109, 54, 130, 7, 37, 119, 150, 69, 5, 73,
129, 124,
47, 78, 138, 57, 98, 41, 86, 84, 89, 115, 42, 18, 148, 128, 83, 134, 96, 90, 4, 102, 94, 44,
121, 46, 101,
88, 3, 110, 79, 141, 10, 28, 20, 108, 29, 64, 32, 85, 59, 36, 75, 62, 25, 65, 68, 17, 52, 66,
106, 8, 72,
99, 55, 27, 53, 140, 11, 13, 48, 60, 15, 12, 33, 63, 122, 114, 22, 24, 82, 103, 142, 97, 21,
38, 45, 136,
120, 95, 9, 131, 19, 74};

int m = sizeof(arr2) / sizeof(arr2[0]);

trials = 10;
double total_time2 = 0;

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


auto start = chrono::high_resolution_clock::now();
selection_sort(arr2, n);
auto end = chrono::high_resolution_clock::now();
double time_taken2 = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken2 / 1e9 << " seconds" <<
endl;
total_time2 += time_taken2;
}
cout<<endl;
double avg_time2 = total_time2 / trials;
cout << "Average time taken for average case " << trials << " trials: " << avg_time2 / 1e9
<< " seconds" << endl;
cout<<endl;

int arr3[250] =
{300,299,296,295,294,293,292,291,290,289,288,286,285,284,283,282,281,280,279,278,277,
276,275,

274,273,272,271,270,269,267,266,265,263,262,261,260,259,258,257,256,255,254,253,251,2
50,248,247,246,245,244,

242,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,223,222,221,220,2
19,218,217,216,215,214,

213,210,209,208,207,206,204,203,202,200,199,198,197,196,195,194,193,192,190,189,188,1
87,186,185,184,183,182,

181,180,179,178,177,176,175,173,172,171,170,168,166,165,164,163,162,161,160,159,158,1
57,156,155,154,152,151,

150,149,147,145,144,143,141,140,138,137,136,135,133,132,131,130,129,128,125,124,123,1
22,121,120,118,117,115,

114,113,111,110,109,108,106,105,104,103,101,100,99,98,97,96,95,91,90,88,87,86,85,84,82,
81,80,79,78,77,76,74,

72,71,70,69,68,67,66,64,63,61,59,58,57,56,54,53,52,51,50,49,48,47,46,45,44,43,42,41,39,38,
37,35,34,33,32,31,
30,28,27,26,24,23,22,21,20,18,16,15,14,13,11,10,9,8,7,6,4,3,2,1};

int p = sizeof(arr3) / sizeof(arr3[0]);

trials = 10;
double total_time3 = 0;

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


auto start = chrono::high_resolution_clock::now();
selection_sort(arr3, n);
auto end = chrono::high_resolution_clock::now();
double time_taken3 = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken3 / 1e9 << " seconds" <<
endl;
total_time3 += time_taken3;
}
cout<<endl;
double avg_time3 = total_time3 / trials;
cout << "Average time taken for worst case " << trials << " trials: " << avg_time3 / 1e9 <<
" seconds" << endl;
cout<<endl;

<chrono> is a header file in the C++ standard library that provides functions for measuring
time complexity and time points.

 Insertion Sort
Code:
#include <iostream>
#include <chrono>
using namespace std;

void insertion_sort(int array[], int size) {


for (int step = 1; step < size; step++) {
int key = array[step];
int j = step - 1;
while (key < array[j] && j >= 0) {
array[j + 1] = array[j];
--j;
}
array[j + 1] = key;
}
}

int main(){
int arr1[50] = {5, 8, 9, 13, 14, 18, 20, 22, 28, 33, 38, 45, 52, 53, 55, 58, 65, 67, 70, 71, 73,
76, 84, 87,
88, 93, 95, 96, 100, 101, 109, 111, 115, 120, 121, 127, 134, 136, 138, 139, 140, 143, 150,
151, 153, 155, 175,
182, 193, 196};

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

int trials = 10;


double total_time = 0;

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


auto start = chrono::high_resolution_clock::now();
insertion_sort(arr1, n);
auto end = chrono::high_resolution_clock::now();
double time_taken = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken / 1e9 << " seconds" <<
endl;
total_time += time_taken;
}
cout<<endl;
double avg_time = total_time / trials;
cout << "Average time taken for best case " << trials << " trials: " << avg_time / 1e9 << "
seconds" << endl;
cout<<endl;

int arr2[150] = {565, 956, 84, 786, 719, 546, 419, 310, 656, 733, 265, 710, 295, 108, 949,
332, 118, 342,
423, 307, 799, 36, 247, 392, 35, 248, 688, 70, 99, 679, 158, 840, 151, 261, 74, 89, 478,
473, 901, 129,
649, 122, 970, 125, 259, 42, 858, 689, 600, 428, 405, 629, 847, 740, 416, 987, 921, 348,
928, 782, 486,
828, 487, 770, 438, 226, 479, 822, 854, 394, 678, 481, 622, 807, 974, 195, 243, 643, 385,
570, 850, 601, 716,
119, 463, 667, 610, 950, 418, 399, 209, 288, 661, 554, 341, 366, 176, 924, 154, 222, 808,
311, 105, 789, 56,
758, 668, 980, 464, 467, 485, 833, 897, 836, 682, 997, 552, 316, 318, 278, 819, 269, 746,
747, 726, 961, 324,
101, 407, 775, 834, 305, 748, 572, 338, 973, 511, 771, 879, 756, 513, 17, 337, 495, 715,
466, 116, 881, 15,
170};

int m = sizeof(arr2) / sizeof(arr2[0]);

trials = 10;
double total_time2 = 0;

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


auto start = chrono::high_resolution_clock::now();
insertion_sort(arr2, n);
auto end = chrono::high_resolution_clock::now();
double time_taken2 = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken2 / 1e9 << " seconds" <<
endl;
total_time2 += time_taken2;
}
cout<<endl;
double avg_time2 = total_time2 / trials;
cout << "Average time taken for average case " << trials << " trials: " << avg_time2 / 1e9
<< " seconds" << endl;
cout<<endl;

int arr3[250] =
{1997,1993,1984,1979,1970,1969,1967,1960,1946,1930,1919,1910,1908,1898,1889,1885,18
61,1859,

1855,1853,1852,1849,1843,1832,1827,1822,1820,1813,1807,1775,1774,1773,1763,1762,175
6,1754,1746,1741,1738,

1723,1721,1705,1693,1691,1667,1657,1633,1612,1604,1582,1576,1572,1556,1554,1549,153
6,1532,1531,1529,1525,

1514,1508,1504,1503,1483,1481,1472,1467,1461,1459,1455,1437,1434,1430,1427,1415,139
9,1386,1373,1369,1357,

1339,1325,1320,1316,1314,1313,1304,1290,1288,1277,1266,1260,1253,1236,1224,1223,121
6,1213,1202,1192,1186,

1183,1169,1162,1141,1140,1135,1129,1127,1122,1120,1116,1113,1094,1087,1075,1069,106
0,1042,1029,999,990,978,

965,964,955,941,926,925,921,919,907,895,894,886,868,858,849,832,826,813,808,803,795,7
75,769,740,738,736,731,

729,725,723,719,715,712,705,700,686,685,676,672,668,666,662,652,646,645,636,633,631,6
25,615,607,600,592,590,

584,583,578,554,537,533,529,525,518,506,494,484,481,470,454,441,436,430,425,422,401,3
95,388,369,362,347,343,

340,317,312,306,301,300,299,274,265,259,228,224,220,209,205,198,190,188,182,181,167,1
50,142,133,125,118,116,
111,110,99,98,90,74,63,53,51,44,41,37,35,33,32,27,22,13};

int p = sizeof(arr3) / sizeof(arr3[0]);


trials = 10;
double total_time3 = 0;

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


auto start = chrono::high_resolution_clock::now();
insertion_sort(arr3, n);
auto end = chrono::high_resolution_clock::now();
double time_taken3 = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken3 / 1e9 << " seconds" <<
endl;
total_time3 += time_taken3;
}
cout<<endl;
double avg_time3 = total_time3 / trials;
cout << "Average time taken for worst case " << trials << " trials: " << avg_time3 / 1e9 <<
" seconds" << endl;
cout<<endl;

 Bubble Sort
Code:
#include <iostream>
#include <chrono>
using namespace std;

void bubble_sort(int array[], int size) {

for (int step = 0; step < size; ++step) {


for (int i = 0; i < size - step; ++i) {

if (array[i] > array[i + 1]) {

int temp = array[i];


array[i] = array[i + 1];
array[i + 1] = temp;
}
}
}
}

int main(){
int arr1[50] = {5, 8, 9, 13, 14, 18, 20, 22, 28, 33, 38, 45, 52, 53, 55, 58, 65, 67, 70, 71, 73,
76, 84, 87,
88, 93, 95, 96, 100, 101, 109, 111, 115, 120, 121, 127, 134, 136, 138, 139, 140, 143, 150,
151, 153, 155, 175,
182, 193, 196};

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

int trials = 10;


double total_time = 0;

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


auto start = chrono::high_resolution_clock::now();
bubble_sort(arr1, n);
auto end = chrono::high_resolution_clock::now();
double time_taken = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken / 1e9 << " seconds" <<
endl;
total_time += time_taken;
}
cout<<endl;
double avg_time = total_time / trials;
cout << "Average time taken for best case " << trials << " trials: " << avg_time / 1e9 << "
seconds" << endl;
cout<<endl;

int arr2[150] = {565, 956, 84, 786, 719, 546, 419, 310, 656, 733, 265, 710, 295, 108, 949,
332, 118, 342,
423, 307, 799, 36, 247, 392, 35, 248, 688, 70, 99, 679, 158, 840, 151, 261, 74, 89, 478,
473, 901, 129,
649, 122, 970, 125, 259, 42, 858, 689, 600, 428, 405, 629, 847, 740, 416, 987, 921, 348,
928, 782, 486,
828, 487, 770, 438, 226, 479, 822, 854, 394, 678, 481, 622, 807, 974, 195, 243, 643, 385,
570, 850, 601, 716,
119, 463, 667, 610, 950, 418, 399, 209, 288, 661, 554, 341, 366, 176, 924, 154, 222, 808,
311, 105, 789, 56,
758, 668, 980, 464, 467, 485, 833, 897, 836, 682, 997, 552, 316, 318, 278, 819, 269, 746,
747, 726, 961, 324,
101, 407, 775, 834, 305, 748, 572, 338, 973, 511, 771, 879, 756, 513, 17, 337, 495, 715,
466, 116, 881, 15,
170};

int m = sizeof(arr2) / sizeof(arr2[0]);

trials = 10;
double total_time2 = 0;

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


auto start = chrono::high_resolution_clock::now();
bubble_sort(arr2, n);
auto end = chrono::high_resolution_clock::now();
double time_taken2 = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken2 / 1e9 << " seconds" <<
endl;
total_time2 += time_taken2;
}
cout<<endl;
double avg_time2 = total_time2 / trials;
cout << "Average time taken for average case " << trials << " trials: " << avg_time2 / 1e9
<< " seconds" << endl;
cout<<endl;

int arr3[250] =
{1997,1993,1984,1979,1970,1969,1967,1960,1946,1930,1919,1910,1908,1898,1889,1885,18
61,1859,
1855,1853,1852,1849,1843,1832,1827,1822,1820,1813,1807,1775,1774,1773,1763,1762,1
756,1754,1746,1741,1738,
1723,1721,1705,1693,1691,1667,1657,1633,1612,1604,1582,1576,1572,1556,1554,1549,1
536,1532,1531,1529,1525,
1514,1508,1504,1503,1483,1481,1472,1467,1461,1459,1455,1437,1434,1430,1427,1415,1
399,1386,1373,1369,1357,
1339,1325,1320,1316,1314,1313,1304,1290,1288,1277,1266,1260,1253,1236,1224,1223,1
216,1213,1202,1192,1186,
1183,1169,1162,1141,1140,1135,1129,1127,1122,1120,1116,1113,1094,1087,1075,1069,1
060,1042,1029,999,990,978,
965,964,955,941,926,925,921,919,907,895,894,886,868,858,849,832,826,813,808,803,795
,775,769,740,738,736,731,
729,725,723,719,715,712,705,700,686,685,676,672,668,666,662,652,646,645,636,633,631
,625,615,607,600,592,590,
584,583,578,554,537,533,529,525,518,506,494,484,481,470,454,441,436,430,425,422,401
,395,388,369,362,347,343,
340,317,312,306,301,300,299,274,265,259,228,224,220,209,205,198,190,188,182,181,167
,150,142,133,125,118,116,
111,110,99,98,90,74,63,53,51,44,41,37,35,33,32,27,22,13};

int p = sizeof(arr3) / sizeof(arr3[0]);

trials = 10;
double total_time3 = 0;

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


auto start = chrono::high_resolution_clock::now();
bubble_sort(arr3, n);
auto end = chrono::high_resolution_clock::now();
double time_taken3 = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Time taken for trial " << i+1 << ": " << time_taken3 / 1e9 << " seconds" <<
endl;
total_time3 += time_taken3;
}
cout<<endl;
double avg_time3 = total_time3 / trials;
cout << "Average time taken for worst case " << trials << " trials: " << avg_time3 / 1e9 <<
" seconds" << endl;
cout<<endl;

Best case for selection sort


Running time
9.00E-01

8.00E-01

7.00E-01

6.00E-01

5.00E-01

4.00E-01

3.00E-01

2.00E-01

1.00E-01

0.00E+00
0 200 400 600 800 1000 1200

Average case for selection sort

running time
0.9

0.8

0.7

0.6

0.5

0.4

0.3

0.2

0.1

0
0 200 400 600 800 1000 1200 1400 1600
Worst case for selection sort

running time
1.20E-04

1.00E-04

8.00E-05

6.00E-05

4.00E-05

2.00E-05

0.00E+00
0 200 400 600 800 1000 1200 1400 1600

Best case for Insertion sort

running time
9.00E-01

8.00E-01

7.00E-01

6.00E-01

5.00E-01

4.00E-01

3.00E-01

2.00E-01

1.00E-01

0.00E+00
0 200 400 600 800 1000 1200

Average case for Insertion sort


Running time
8.00E-05

7.00E-05

6.00E-05

5.00E-05

4.00E-05

3.00E-05

2.00E-05

1.00E-05

0.00E+00
0 200 400 600 800 1000 1200

Worst case for insertion sort

Y-Values
6.00E-04

5.00E-04

4.00E-04

3.00E-04

2.00E-04

1.00E-04

0.00E+00
0 200 400 600 800 1000 1200 1400 1600

You might also like