0% found this document useful (0 votes)
102 views18 pages

C++ Sorting Algorithms Implementation

Uploaded by

prabhumiui328
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
102 views18 pages

C++ Sorting Algorithms Implementation

Uploaded by

prabhumiui328
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Prabhat Anand Tiwari Practical no.

3 2024510066

Aim: To implement and analyze searching algorithms, Linear Search and Binary Search

Objectives:
1. To implement the Bubble Sort algorithm.
2. To implement the Insertion Sort algorithm.
3. To implement the Selection Sort algorithm.
4. To implement the Quick Sort algorithm.
5. To implement the Radix Sort algorithm.
6. To implement the Merge Sort algorithm.
7. To compare the time complexity of all the algorithms.
8. To understand when each algorithm is best suited for use.

Tools Used: Online C++ Compiler - Programiz

Concept:

Bubble Sort Algorithm:

1. Start
2. Input the array to be sorted
3. Repeat the following steps until no swaps are made in a complete pass through
the array:
● Loop through the array from the first element to the (n-1)th element:
○ If the current element is greater than the next element:
■ Swap the elements
● Print the array status after every pass
4. End

Selection Sort Algorithm:

1. Start
2. Input the array to be sorted
3. Loop through the array from the first element to the (n-1)th element:
● Find the smallest element from the unsorted part of the array
● Swap the smallest element with the first element of the unsorted array
● Print the array status after every pass
4. End
Prabhat Anand Tiwari Practical no. 3 2024510066

Insertion Sort Algorithm:

1. Start
2. Input the array to be sorted
3. Loop through the array starting from the second element:
● Set the current element as the key
● Insert the key in sorted array by:
○ Compare the key with elements in the sorted array and shift them
to the right if they are larger than the key
○ Insert the key when the element to left is smaller than the key
● Print the array status after every pass
4. End

Quick Sort Algorithm:


1. Start
2. Input the array to be sorted
3. Set 0th element as pivot
4. Partition the array such that the elements to the left of pivot are smaller than the
pivot and elements to the right of pivot are greater than the pivot
5. Repeat step 4 to the left and right subarrays until the array is sorted (recursion)
6. End

Radix Sort Algorithm:


1. Start
2. Input the array to be sorted
3. Find the maximum number and calculate its number of digits
4. Sort array on the basis of each digit, starting from the least significant digit to the
most significant digit
5. Print the array after sorting by each digit
6. Repeat until MSB has been processed
7. End

Merge Sort Algorithm:


1. Start
2. Input the array to be sorted
3. Divide the array into two halves
4. Recursively apply merge sort to each half
5. Merge the two sorted halves together
Prabhat Anand Tiwari Practical no. 3 2024510066

6. Repeat until the entire array is sorted


7. End

Problem Statement:
Implement Bubble, Selection, Insertion, Quick, Radix and Merge sort techniques
in c++.

Solution:
Bubble Sort:

#include <iostream>
using namespace std;

class BubbleSort
{
public:
int *arr;
int size;

void bubbleSort(int arr[])


{
for (int i = 0; i < size - 1; i++)
{
for (int j = 0; j < size - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
arr[j] += arr[j + 1];
arr[j + 1] = arr[j] - arr[j + 1];
arr[j] -= arr[j + 1];
}
}
// print pass
cout << "Pass " << i + 1 << ": ";
for (int i = 0; i < size; i++)
{
cout << arr[i] << ' ';
}
Prabhat Anand Tiwari Practical no. 3 2024510066

cout << endl;


}
}

int *getInput()
{
cout << "Enter size of array: ";
cin >> size;
int *arr = new int[size];
for (int i = 0; i < size; i++)
{
cout << "Enter value of element at position " << i << ": ";
cin >> arr[i];
}
return arr;
}
};

int main()
{
BubbleSort bs1;
int *arr = [Link]();
[Link](arr);
return 0;
}

Output:
Prabhat Anand Tiwari Practical no. 3 2024510066

Selection Sort:

#include <iostream>
using namespace std;

class SelectionSort
{
public:
int *arr;
int size;

void selectionSort(int arr[])


{
for (int i = 1; i < size; i++)
{
int min = i - 1;
for (int j = i; j < size; j++)
{
if (arr[min] > arr[j])
{
min = j;
}
}
// swap min and i
// using temp since same index swapping results in 0 with addition
subtraction method
int temp = arr[min];
arr[min] = arr[i - 1];
arr[i - 1] = temp;
// print pass
cout << "Pass " << i << ": ";
for (int j = 0; j < size; j++)
{
cout << arr[j] << ' ';
}
cout << endl;
}
}

int *getInput()
Prabhat Anand Tiwari Practical no. 3 2024510066

{
cout << "Enter size of array: ";
cin >> size;
int *arr = new int[size];
for (int i = 0; i < size; i++)
{
cout << "Enter value of element at position " << i << ": ";
cin >> arr[i];
}
return arr;
}
};

int main()
{
SelectionSort is1;
int *arr = [Link]();
[Link](arr);
return 0;
}

Output:
Prabhat Anand Tiwari Practical no. 3 2024510066

Insertion Sort:

#include <iostream>
using namespace std;

class InsertionSort
{
public:
int *arr;
int size;

void insertionSort(int arr[])


{
for (int i = 1; i < size; i++)
{
if (arr[i - 1] > arr[i])
{
// swap i-1 and i
arr[i - 1] += arr[i];
arr[i] = arr[i - 1] - arr[i];
arr[i - 1] -= arr[i];
// compare i-1 with previous elements
for (int j = i - 1; j > 0; j--)
{
// swap if needed
if (arr[j - 1] > arr[j])
{
arr[j - 1] += arr[j];
arr[j] = arr[j - 1] - arr[j];
arr[j - 1] -= arr[j];
}
else
{
break;
}
}
}
// print pass
cout << "Pass " << i << ": ";
for (int j = 0; j <= i; j++)
Prabhat Anand Tiwari Practical no. 3 2024510066

{
cout << arr[j] << ' ';
}
cout << endl;
}
}

int *getInput()
{
cout << "Enter size of array: ";
cin >> size;
int *arr = new int[size];
for (int i = 0; i < size; i++)
{
cout << "Enter value of element at position " << i << ": ";
cin >> arr[i];
}
return arr;
}
};

int main()
{
int size = 0;
InsertionSort is1;
int *arr = [Link]();
[Link](arr);
return 0;
}
Prabhat Anand Tiwari Practical no. 3 2024510066

Output:
Prabhat Anand Tiwari Practical no. 3 2024510066

Quick Sort:

#include <iostream>
using namespace std;

class QuickSort {
public:
int size;

int* getInput() {
cout << "Enter size of array: ";
cin >> size;
int* arr = new int[size];

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


cout << "Enter value of element at position " << i << ": ";
cin >> arr[i];
}
return arr;
}

int partition(int arr[], int start, int end) {


int pivot = arr[end];
int i = start - 1;

for (int j = start; j <= end - 1; j++) {


if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}

swap(arr[i + 1], arr[end]);


return (i + 1);
}

void quickSort(int arr[], int start, int end) {


if (start < end) {
int pivotIndex = partition(arr, start, end);
Prabhat Anand Tiwari Practical no. 3 2024510066

quickSort(arr, start, pivotIndex - 1);


quickSort(arr, pivotIndex + 1, end);
}
}

// print the array


void printArray(int arr[]) {
for (int i = 0; i < size; i++)
cout << arr[i] << " ";
cout << endl;
}
};

int main() {
QuickSort quickSortObj;
int* array = [Link]();
[Link](array, 0, [Link] - 1);

cout << "Sorted array: ";


[Link](array);

return 0;
}

Output:
Prabhat Anand Tiwari Practical no. 3 2024510066

Radix Sort:

#include <iostream>
#include <vector>
using namespace std;

class RadixSort
{
public:
int *array;
int max = 0;
int size = 0;
int digits = 0;

void findMaxDigit(int arr[])


{
// Find largest number
for (int i = 0; i < size; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
// Find number of digits in largest number
int tempMax = max;
while (tempMax > 0)
{
tempMax = tempMax / 10;
digits++;
}
}

void radixSort(int arr[])


{
int divisor = 1;
for (int i = 0; i < digits; i++)
{
// Store elements in the buckets according to the digit place
vector<vector<int>> bucket(10);
Prabhat Anand Tiwari Practical no. 3 2024510066

for (int j = 0; j < size; j++)


{
bucket[(arr[j] / divisor) % 10].push_back(arr[j]);
}
divisor *= 10;
// Rearrange array elements and print passes
int index = 0;
cout << "Pass " << i + 1 << ": ";
for (int j = 0; j < 10; j++)
{
for (int element : bucket[j])
{
cout << element << ' ';
arr[index] = element;
index++;
}
}
cout << endl;
}
}

int *getInput()
{
cout << "Enter size of array: ";
cin >> size;
int *arr = new int[size];
for (int i = 0; i < size; i++)
{
cout << "Enter value of element at position " << i << ": ";
cin >> arr[i];
}
return arr;
}
};

int main()
{
RadixSort rs;
int *arrayLoc = [Link]();
[Link](arrayLoc);
Prabhat Anand Tiwari Practical no. 3 2024510066

[Link](arrayLoc);
return 0;
}

Output:
Prabhat Anand Tiwari Practical no. 3 2024510066

Merge Sort:

#include <iostream>
using namespace std;

class MergeSort
{
public:
int size;

int *getInput()
{
cout << "Enter size of array: ";
cin >> size;
int *arr = new int[size];
for (int i = 0; i < size; i++)
{
cout << "Enter value of element at position " << i << ": ";
cin >> arr[i];
}
return arr;
}

void merge(int arr[], int left, int mid, int right)


{
int lSize = mid - left + 1;
int rSize = right - mid;

int *leftArr = new int[lSize];


int *rightArr = new int[rSize];

for (int i = 0; i < lSize; i++)


leftArr[i] = arr[left + i];
for (int i = 0; i < rSize; i++)
rightArr[i] = arr[mid + 1 + i];

int i = 0;
int j = 0;
int k = left;
while (i < lSize && j < rSize)
Prabhat Anand Tiwari Practical no. 3 2024510066

{
if (leftArr[i] <= rightArr[j])
{
arr[k] = leftArr[i];
i++;
}
else
{
arr[k] = rightArr[j];
j++;
}
k++;
}

while (i < lSize)


{
arr[k] = leftArr[i];
i++;
k++;
}

while (j < rSize)


{
arr[k] = rightArr[j];
j++;
k++;
}
}

void mergeSort(int arr[], int left, int right)


{
if (left < right)
{
int mid = left + (right - left) / 2;

mergeSort(arr, left, mid);


mergeSort(arr, mid + 1, right);

merge(arr, left, mid, right);


}
Prabhat Anand Tiwari Practical no. 3 2024510066

// print the array


void printArray(int arr[])
{
for (int i = 0; i < size; i++)
cout << arr[i] << " ";
cout << endl;
}
};

int main()
{

MergeSort ms;
int *array = [Link]();
[Link](array, 0, [Link] - 1);

cout << "Sorted array: ";


[Link](array);

return 0;
}

Output:
Prabhat Anand Tiwari Practical no. 3 2024510066

Observation:
Bubble Sort is an easy to implement algorithm, but it is not very efficient. It swaps
adjacent elements if they are in the wrong order, making it easy to understand and
implement. But has a time complexity of O(n²). It can be applied to both positive and
negative numbers but is inefficient for large datasets because of its quadratic time
complexity. It performs many unnecessary comparisons and swaps even if the array is
partially sorted.

Selection Sort is easy to understand and implement but is also not efficient for large
datasets. It works by repeatedly finding the minimum element from the unsorted portion
of the array and swapping it with the first unsorted element. Like Bubble Sort, it has a
time complexity of O(n²), which makes it impractical for large datasets. Selection Sort
performs a fixed number of comparisons regardless of the initial order of the array.
However, it minimizes the number of swaps.

Insertion Sort is relatively efficient for small or nearly sorted datasets but can be slow in
the worst case and with larger datasets. It works by gradually building a sorted array by
picking each element and inserting it into its correct position. It performs much better
when the input is already partially sorted, with a best-case time complexity of O(n).

Quick Sort is an efficient algorithm that performs well on average, with a time complexity
of O(n log n). It works by selecting a pivot element and partitioning the array such that
elements smaller than the pivot are placed on its left, and larger elements on its right.
However, in the worst case (when the array is already sorted or nearly sorted), its time
complexity becomes O(n²).

Radix Sort is a sorting algorithm where we don’t compare elements. It processes the
numbers digit by digit, starting from the least significant digit to the most significant digit.
Its time complexity is O(d * n), where d is the number of digits, and n is the number of
elements in the array, making it more efficient than previous sorting algorithms.
However, it cannot be used for sorting negative integers.

Merge Sort is an efficient sorting algorithm that has a constant time complexity of O(n
log n), regardless of the input. It divides the array into two halves, recursively sorts each
half, and then merges the sorted halves together. Merge Sort is particularly useful for
large datasets because of its performance. However, it requires additional memory
proportional to the size of the array. Merge Sort can handle both positive and negative
numbers.

Common questions

Powered by AI

The primary conceptual difference between Merge Sort and Quick Sort is in their approach to sorting. Merge Sort uses a divide-and-conquer method by dividing the array into two halves, recursively sorting each, and merging them . This means that Merge Sort focuses on merging sorted arrays. Quick Sort, on the other hand, revolves around selecting a pivot to partition the array such that elements less than the pivot are on one side and those greater on the other, recursively applying the process to the partitions . Merge Sort's approach ensures stable sorting, whereas Quick Sort's pivot-based partitioning can be unstable depending on pivot choice and input data.Quick Sort focuses on partitioning based on the pivot point, recursively applying the same logic to the partitions .

Quick Sort's reliance on a pivot can be a drawback because performance can significantly vary based on the pivot selection. If the pivot results in uneven partitions, such as always selecting the smallest or largest element, the algorithm degrades to its worst-case time complexity of O(n²), particularly for already sorted or nearly sorted data . This variability makes performance inconsistent across different data sets, as the algorithm's divide-and-conquer efficiency hinges on balanced partitioning. Strategies like randomized pivot or median-of-three can help mitigate these effects and lead to better average-case performance .

Selection Sort distinguishes itself by repeatedly finding the smallest unsorted element and swapping it with the first unsorted element in the array. This method ensures that each pass reduces the size of the unsorted portion by accurately placing one element at a time . However, the inefficiency lies in its fixed number of comparisons per pass, regardless of the data's initial arrangement. It always performs O(n²) comparisons without taking advantage of any partial sorting that may exist, thus limiting its performance efficiency .

Bubble Sort, despite its inefficiency, is often taught as an introductory algorithm because of its simplicity. It is easy to understand as it involves only comparing and swapping adjacent elements until the array is sorted . This makes it a good teaching tool for explaining basic concepts of sorting and iterative algorithms. However, its inefficiency is highlighted by its O(n²) time complexity, which makes it unsuitable for large datasets as it performs unnecessary comparisons and swaps even with partially sorted arrays .

Quick Sort is generally efficient due to its average time complexity of O(n log n) and its process of selecting a pivot and partitioning the array into smaller and larger elements relative to the pivot. This often results in a well-balanced division of the array . However, Quick Sort's performance degrades to O(n²) in the worst case, particularly when the array is already sorted or nearly sorted, and poor pivot choices consistently result in highly unbalanced partitions .

Radix Sort is more efficient than some comparison-based sorting algorithms because its time complexity is O(d * n), where d is the number of digits and n is the number of elements, which can be more efficient than O(n log n) for large datasets with small d . However, a limitation of Radix Sort is that it cannot handle negative integers as it relies on the position value of digits .

Merge Sort offers a significant advantage in handling large datasets due to its consistent time complexity of O(n log n), which ensures efficient performance regardless of the input data ordering . This makes it particularly reliable for large datasets where other algorithms with varying time complexities like Quick Sort might degrade to O(n²) under certain conditions. Although Merge Sort requires additional memory proportional to the input size due to temporary arrays needed for merging, this space cost is often justified by the stable and predictable efficiency it provides .

Merge Sort maintains a consistent time complexity of O(n log n) through its divide-and-conquer approach, dividing the array into two halves, recursively sorting each half, and merging them back together . It is efficient across all inputs because each level of recursion requires linear time proportional to the array's size, and there are logarithmic levels of recursion. However, Merge Sort requires additional memory proportional to the size of the array since it needs space for the temporary arrays used during merging .

Both Bubble Sort and Selection Sort have a time complexity of O(n²), which makes them inefficient for large datasets . Bubble Sort repeatedly swaps adjacent elements if they are in the wrong order, which results in many unnecessary comparisons and swaps even if the array is partially sorted . Selection Sort repeatedly finds the minimum element from the unsorted portion of the array and swaps it with the first unsorted element; it performs a fixed number of comparisons regardless of the initial order of the array but minimizes the number of swaps .

Insertion Sort is relatively efficient for small or nearly sorted datasets due to its best-case time complexity of O(n) when the input is already partially sorted . It works by gradually building a sorted array by placing each element into its correct position. However, Insertion Sort can be slow in the worst case and with larger datasets due to its O(n²) time complexity, especially when the input is reversed or large .

You might also like