1.
Define Sorting
In data structures and algorithms, sorting is the process of arranging elements of a collection (such as an
array or list) in a specific order, typically in ascending or descending order. Sorting is essential because it
helps organize data, making it easier to search, analyze, and optimize the efficiency of other algorithms.
For example, binary search requires a sorted list to function correctly.
Common Sorting Algorithms:
Bubble Sort: Compares adjacent elements and swaps them if they are in the wrong order.
Selection Sort: Repeatedly selects the minimum (or maximum) element from the unsorted part and
moves it to the beginning.
Insertion Sort: Builds the final sorted array one item at a time by inserting elements into their correct
position.
Merge Sort: Divides the list into halves, recursively sorts each half, and then merges the sorted halves.
Quick Sort: Selects a pivot element and partitions the array such that elements less than the pivot come
before it and greater elements come after, then sorts recursively.
Heap Sort: Converts the list into a heap structure, then repeatedly extracts the maximum (or minimum)
element to form a sorted sequence.
Complexity:
Sorting algorithms vary in their time complexity, from for simpler algorithms like Bubble Sort to for
efficient algorithms like Merge Sort and Quick Sort. The choice of sorting algorithm depends on the data
size, order, and memory constraints.
2. Write the function in C for insertion sort?
Here's a C function that implements the Insertion Sort algorithm. This function sorts an array of integers
in ascending order.
Here's a more concise version of the Insertion Sort function in C:
#include <stdio.h>
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i], j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
arr[j + 1] = key;
int main() {
int arr[] = {12, 11, 13, 5, 6};
int n = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, n);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
return 0;
Explanation:
This is a minimal implementation:
The insertionSort function performs the insertion sort as before, shifting elements greater than the key.
The main function sorts and prints the array.
The function insertionSort takes an array arr and its size n as input.
It iterates over each element starting from the second element (i = 1).
For each element, it shifts all elements greater than the current element (key) one position to the right.
The key is then inserted in its correct position, making the left side of the array sorted incrementally.
Output
The sorted output would be:
5 6 11 12 13
Q.3 Explain the searching algorithms.
1. Linear Search
Description: Linear search goes through each element in a list one by one until it finds the target or
reaches the end.
Best Use: Small or unsorted datasets.
Time Complexity: O(n) in the worst case, where is the number of elements.
2. Binary Search
Description: Binary search works on sorted lists by dividing the list in half. It compares the middle
element to the target and then eliminates half of the remaining elements based on whether the target is
greater or smaller than the middle element.
Best Use: Large, sorted datasets.
Time Complexity: O (log n) in the worst case.
3. Jump Search
Description: Jump search involves jumping ahead by fixed steps (e.g., ) in a sorted list. When the target
value is found to be smaller than the current element, it does a linear search backward within the
previous block.
Best Use: Sorted arrays where binary search might be inefficient.
Time Complexity: O(√n)
4. Interpolation Search
Description: Interpolation search estimates the target’s position based on the values at the ends. It
works well for uniformly distributed data, where it can jump closer to the target using a position
formula.
Best Use: Sorted, uniformly distributed data.
Time Complexity: O(log log n) the best case; in the worst case if data is not uniformly distributed.
5. Exponential Search
Description: Exponential search works by first finding a range in which the target might exist by
exponentially increasing the index, then performing a binary search within this range.
Best Use: Sorted arrays.
Time Complexity: O(log n)
6. Fibonacci Search
Description: Fibonacci search is similar to binary search but uses Fibonacci numbers to divide the array
into smaller parts. It searches within the range based on Fibonacci sequences.
Best Use: Large, sorted arrays.
Time Complexity:O(log n)
Each algorithm has specific cases where it is most efficient, depending largely on the data’s structure,
distribution, and whether it’s sorted.
Q4. Explain the sorting algorithms and give comparative analysis .
Here are explanations of common sorting algorithms, along with a comparative analysis:
*1. Bubble Sort*
- Works by repeatedly swapping adjacent elements if they're in the wrong order.
- Repeats the process until no more swaps are needed.
- Time complexity: O(n^2)
- Space complexity: O(1)
- Stable: Yes
*2. Selection Sort*
- Divides the array into sorted and unsorted regions.
- Selects the smallest element from the unsorted region and swaps it with the first element.
- Repeats the process until the array is sorted.
- Time complexity: O(n^2)
- Space complexity: O(1)
- Stable: No
*3. Insertion Sort*
- Builds the sorted array one element at a time.
- Inserts each element into its proper position in the sorted region.
- Time complexity: O(n^2)
- Space complexity: O(1)
- Stable: Yes
*4. Merge Sort*
- Divides the array into smaller chunks and sorts each recursively.
- Merges the sorted chunks back together.
- Time complexity: O(n log n)
- Space complexity: O(n)
- Stable: Yes
*5. Quick Sort*
- Selects a pivot element and partitions the array around it.
- Recursively sorts the subarrays.
- Time complexity: O(n log n) average, O(n^2) worst-case
- Space complexity: O(log n)
- Stable: No
*6. Heap Sort*
- Builds a heap from the array.
- Repeatedly removes the largest element and rebuilds the heap.
- Time complexity: O(n log n)
- Space complexity: O(1)
- Stable: No
*7. Radix Sort*
- Sorts integers based on their digits.
- Uses counting sort or bucket sort.
- Time complexity: O(nk)
- Space complexity: O(nk)
- Stable: Yes
*8. Timsort*
- Hybrid of merge sort and insertion sort.
- Optimized for real-world data.
- Time complexity: O(n log n)
- Space complexity: O(n)
- Stable: Yes
Consider factors such as:
1. Data size and complexity
2. Performance requirements
3. Stability (preserving order of equal elements)
4. Space constraints
5. Real-world data distribution
*Recommendations*
- For small datasets: Insertion Sort or Bubble Sort
- For large datasets: Merge Sort, Quick Sort, or Timsort
- For nearly sorted data: Insertion Sort or Timsort
- For integers: Radix Sort
- For stability: Merge Sort or Timsort
Q. 5 Write a C program to sort the elements using bubble sort, Insertion Sort?
Here's a smaller version of the program focusing only on Bubble Sort and Insertion Sort:
#include <stdio.h>
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++)
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i], j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j]
j--;
}
arr[j + 1] = key;
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
int main() {
int arr[] = {5, 2, 9, 1, 5, 6};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Original array: ");
printArray(arr, n);
bubbleSort(arr, n);
printf("Bubble Sorted array: ");
printArray(arr, n);
int arr2[] = {5, 2, 9, 1, 5, 6};
insertionSort(arr2, n);
printf("Insertion Sorted array: ");
printArray(arr2, n);
return 0;
Explanation
1. bubbleSort and insertionSort functions implement the sorting algorithms.
2. The printArray function displays the array.
3. main initializes an array, sorts it with both methods, and prints the sorted arrays.
You can run the program and see both sorting results for the sample array {5, 2, 9, 1, 5, 6}.
Q.6. Write a C program to perform searching operations using linear search
#include <stdio.h>
int linearSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++)
if (arr[i] == target) return i;
return -1;
int main() {
int arr[] = {5, 2, 9, 1, 5, 6};
int target = 9;
int n = sizeof(arr) / sizeof(arr[0]);
int result = linearSearch(arr, n, target);
if (result != -1)
printf("Element found at index %d\n", result);
else
printf("Element not found\n");
return 0;
}
Explanation:
1. linearSearch: Loops through the array and returns the index of the target if found.
2. main: The array {5, 2, 9, 1, 5, 6} is searched for the target value 9.
The program will output:
Element found at index 2
Q 7. Write an algorithm to implement quick sort with suitable example
1. Choose a pivot from the array (e.g., last element).
2. Partition the array into two sub-arrays:
Left sub-array contains elements smaller than the pivot.
Right sub-array contains elements greater than the pivot.
3. Recursively sort the left and right sub-arrays.
4. The base case is when the sub-array has only one element or is empty.
Pseudocode:
QuickSort(arr[], low, high)
if low < high
pivot_index = Partition(arr[], low, high)
QuickSort(arr[], low, pivot_index - 1)
QuickSort(arr[], pivot_index + 1, high)
Partition(arr[], low, high)
pivot = arr[high]
i = low - 1
for j = low to high - 1
if arr[j] < pivot
i=i+1
Swap arr[i] with arr[j]
Swap arr[i + 1] with arr[high]
return i + 1
Example:
For the array: [10, 7, 8, 9, 1, 5]
1. Choose 5 as pivot:
Partition: [1, 5, 8, 9, 7, 10] (pivot 5 is at index 1).
2. Recursive sorting:
Left sub-array: [1] (already sorted).
Right sub-array: [8, 9, 7, 10]:
Choose 10 as pivot.
Partition: [8, 9, 7, 10] (pivot 10 is in the correct place).
Recursively sort [8, 9, 7]:
Choose 7 as pivot, resulting in [7, 8, 9].
3. Final sorted array: [1, 5, 7, 8, 9, 10]
Time Complexity:
Best & Average Case: O(n log n)
Worst Case: O(n²) (when the pivot selection is poor, like when the array is already sorted)
Quick Sort is efficient with an average time complexity of O(n log n).
Q.8 Write an algorithm for binary search with suitable example
Binary Search Algorithm
Binary Search is a searching algorithm used on a sorted array or list. It works by repeatedly dividing the
search interval in half. If the target value is less than the value in the middle of the array, the search
continues on the left half, otherwise, it continues on the right half.
Algorithm:
1. Set low = 0 and high = n - 1 (where n is the number of elements in the array).
2. While low ≤ high:
Find the middle index: mid = (low + high) / 2.
If arr[mid] == target, return mid (target found).
If arr[mid] < target, set low = mid + 1 (search the right half).
If arr[mid] > target, set high = mid - 1 (search the left half)
3. If the target is not found, return -1 (indicating the target is not present in the array).
Pseudocode:
BinarySearch(arr[], target, low, high)
while low <= high
mid = (low + high) / 2
if arr[mid] == target
return mid
else if arr[mid] < target
low = mid + 1
else
high = mid - 1
return -1
Example:
For the sorted array: [1, 3, 5, 7, 9, 11]
And, let's search for the target = 7.
1. Initial array: [1, 3, 5, 7, 9, 11], low = 0, high = 5
Calculate mid = (0 + 5) / 2 = 2.
arr[2] = 5, which is less than 7, so update low = mid + 1 = 3.
2. New array search: [7, 9, 11], low = 3, high = 5
Calculate mid = (3 + 5) / 2 = 4.
arr[4] = 9, which is greater than 7, so update high = mid - 1 = 3.
3. Final array search: [7], low = 3, high = 3
Calculate mid = (3 + 3) / 2 = 3.
arr[3] = 7, which matches the target.
Return mid = 3.
Output:
Target found at index: 3.
Time Complexity:
Best Case: O(1) (if the target is at the middle element).
Average and Worst Case: O(log n), where n is the number of elements in the array.
Binary Search is efficient for large datasets because it reduces the search space by half with each
comparison.