Ada Practical File
Ada Practical File
Algorithm
Practical File
Submitted By:
A2305217407
B.TECH(6CSE7X)
EXPERIMENT 1
THEORY:
Insertion sort is a simple sorting algorithm that works the way we sort playing cards in our hands.
Code:
#include<iostream>
{
int i,j,key;
for(j=1;j<n;j++)
key = a[j];
i = j-1;
a[i+1] = a[i];
i = i-1;
a[i+1] = key;
int i;
for(i=0;i<n;i++)
cout<<a[i]<<"\n";
cout<<endl;
int main()
int a[10];
int n,i;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
cout<<"ELEMENTS ENTERED:\n";
for(i=0;i<n;i++)
cout<<a[i]<<endl;
insertionSort(a,n);
printArray(a,n);
return 0;
Output:
Insertion sort runs in O(n)O(n) time in its best case and runs in O(n^2)O(n2) in its worst and average
cases.
Use the master theorem to solve this recurrence for the running time. As expected, the algorithm's
complexity is O(n^2) . O(n2). When analysing algorithms, the average case often has the same
complexity as the worst case. So insertion sort, on average, takes O(n^2)O(n2) time.
Insertion sort has a fast-best-case running time and is a good sorting algorithm to use if the input list
is already mostly sorted. For larger or more unordered lists, an algorithm with a faster worst and
average-case running time, such as merge sort, would be a better choice.
THEORY:
Binary search is the most popular Search algorithm. It is efficient and also one of the most
commonly used techniques that is used to solve problems.
If all the names in the world are written down together in order and you want to search for the
position of a specific name, binary search will accomplish this in a maximum of 35 iterations.
Binary search works only on a sorted set of elements. To use binary search on a collection, the
collection must first be sorted.
When binary search is used to perform operations on a sorted set, the number of iterations can
always be reduced on the basis of the value that is being searched.
Code:
#include <iostream>
while (l <= r) {
int m = l + (r - l) / 2;
if (arr[m] == x)
return m;
if (arr[m] < x)
l = m + 1;
else
r = m - 1;
return -1;
int main()
int a[10];
int n,i,k;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
cout<<"ELEMENTS ENTERED:\n";
for(i=0;i<n;i++)
cout<<a[i]<<endl;
cin>>k;
return 0;
Output:
Binary search has a worst-case and average-case running time of O (log n), making O (log n)
comparisons, where nn is the number of elements in the array. The worst case occurs when a given
target element is not in the list at all. This means the algorithm has halved the list again and again
until it reaches a list of size one. To get a list of size nn down to a list of 1 element, log n divisions
must be made. Each step of the binary search halves the search space.Binary search has a O(1) best
case running time. This occurs when the first midpoint selected is the target value.
THEORY:
Quicksort is a fast sorting algorithm that takes a divide-and-conquer approach to sorting lists. While
sorting is a simple concept, it is a basic principle used in complex programs such as file search, data
compression, and pathfinding. Running time is an important thing to consider when selecting a
sorting algorithm since efficiency is often thought of in terms of speed. Quicksort has a very slow
worst-case running time, but a fast average and best-case running time.
quicksort uses divide and conquer to sort an array. Divide and conquer is a technique used for
breaking algorithms down into subproblems, solving the subproblems, and then combining the
results back together to solve the original problem. It can be helpful to think of this method as
divide, conquer, and combine.
Here is the divide, conquer, and combine steps that quicksort uses:
//Quick Sort Algorithm is as follow:
Code:
#include<iostream>
int t = *a;
*a = *b;
*b = t;
int x = a[r];
int i = p-1;
for(int j=p;j<=r-1;j++)
if(a[j] <= x)
i = i+1;
swap(&a[i],&a[j]);
swap(&a[i+1],&a[r]);
return(i+1);
if(p < r)
int q = partition(a,p,r);
quickSort(a,p,q-1);
quickSort(a,q+1,r);
int i;
for(i=0;i<n;i++)
{
cout<<a[i]<<"\n";
cout<<endl;
int main()
int a[10];
int i,n;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
cout<<"ELEMENTS ENTERED:\n";
for(i=0;i<n;i++)
cout<<a[i]<<endl;
quickSort(a,0,n-1);
printArray(a,n);
return 0;
}
Output:
Division: Dividing the list into parts less than and greater than the pivot takes O(n) time because the
algorithm needs to scan through the list, which has O(n) elements. During this step, for each
element, the algorithm performs a constant number of comparisons. In particular, it determines if
the element is greater than or less than the pivot.
Subproblems:
Combining: The subarrays are sorted in other steps of the algorithm, so there is no explicit, separate
combining step.
1. Best-case analysis
The best case recurrence is
The master theorem tells us that the solution to this recurrence is:
Quicksort will have a best-case running time when the pivot at each recursive call is equal to the
median element of the subarray. This means that, at each step, the problem size is being halved, and
the array can be sorted with logn nested calls. Each call takes O(n) time (from the division step), so
the total run time of the best-case quicksort is O(nlogn).
2. Worst-case analysis
The worst-case recurrence is
3. Average-case analysis
The expected run time of the algorithm is also
while the average and best-case run time of quicksort is equal to that of other algorithms such as
merge sort, a well-implemented quicksort will have much lower constant factors than other sorting
algorithms. If two algorithms have the same asymptotic running time, the one with smaller constant
factors will be faster. In practice, quicksort is often faster than merge sort. Quicksort is usually
implemented as an unstable sort with a best-case space complexity of O( \log n)O(logn) and an
average-case space complexity of O(n).
Conclusion: Quick Sort was implemented successfully.
EXPERIMENT 4
AIM: To Implement Merge Sort Algorithm.
THEORY:
Merge sort (sometimes spelled mergesort) is an efficient sorting algorithm that uses a divide-and-
conquer approach to order elements in an array. Sorting is a key tool for many problems in
computer science. For example, inputting a list of names to a sorting algorithm can return them in
alphabetical order, or a sorting algorithm can order a list of basketball players by how many points
they each scored. Running time is an important thing to consider when selecting a sorting algorithm
since efficiency is often thought of in terms of speed. Mergesort runs in a guaranteed O(nlogn) time,
which is significantly faster than the average- and worst-case running times of several other sorting
algorithms.
Sorting may seem like a simple concept, but efficient sorting is critical when dealing with large
amounts of data. Sorting is the basis for more complex computer programs such as searching for
files on a computer, finding the shortest route to a destination, and compressing data.
Mergesort has two steps: merging and sorting. The algorithm uses a divide-and-conquer approach to
merge and sort a list.
Divide and conquer is a technique used for breaking algorithms down into subproblems, solving the
subproblems, and then combining the results back together to solve the original problem. It can be
helpful to think of this method as divide, conquer, and combine.
Complexity of Mergesort
Division:
It takes O(1) time to divide the problem into two parts. To divide the problem, the algorithm
computes the middle of the list by taking the length of the list and dividing by two, which takes
constant time.
Some other sorting algorithms have a faster best-case running time, such as insertion sort, which
runs at best in O(n) time. However, insertion sort has a worst- and average-case running time
of O(n^2), which is much slower than O(n) and O(nlogn). You might choose insertion sort over
mergesort if your list is already mostly sorted—insertion sort would take O(n), while mergesort will
still take O(nlogn). Mergesort is used when we want a guaranteed running time of O(nlogn),
regardless of the state of the input.
Code:
#include<stdlib.h>
#include<stdio.h>
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
i = 0;
j = 0;
k = l;
arr[k] = L[i];
i++;
else
arr[k] = R[j];
j++;
k++;
arr[k] = L[i];
i++;
k++;
{
arr[k] = R[j];
j++;
k++;
if (l < r)
int m = l+(r-l)/2;
mergeSort(arr, l, m);
merge(arr, l, m, r);
int i;
printf("\n");
int main()
{
int a[10];
int i,n;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("ELEMENTS ENTERED:\n");
for(i=0;i<n;i++)
printf("%d\n",a[i]);
//printf("\n");
mergeSort(a, 0, n - 1);
printArray(a,n);
return 0;
}
Output: