Search and Sort

I study Data Structure and Algorithm in GeeksforGeeks and play with the algorithms in C. In this part, I will cover algorithms of searching and sorting!

Header file

Since that some methods are used quite often, I write a header file for this part.

/* File name: util.h */
#include <stdio.h>

/* Function to swap two values */
void swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

/* Function to print an array */
void printArray(int arr[], int size)
{
    int i;
    for (i=0; i < size; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

This algorithm supposes that an array is already sorted and search the sub-array in dependent of the middle number and our search number. Its time complexity T(n)=O(log[n]) .

#include <stdio.h>
// Binary search for half part recursively

int binary_search(int arr[], int l, int r, int x){
    if (r >= l){
        int middle = l + (r-1)/2;
        if ( arr[middle] == x) return middle;
        if ( arr[middle] < x) return binary_search(arr, middle+1, r, x);
        return binary_search(arr, l, middle-1, x);
    }
    return -1;
}

int main(void){

    int arr[] = {1, 2, 4, 5, 6, 9};
    int n = sizeof(arr)/ sizeof(arr[0]);
    int x = 9;
    int result = binary_search(arr, 0, n-1, x);

    (result == -1)? printf("Not Found!\n")
                  : printf("Element is presented at index %d\n", result );

    return 0;
}

This algorithm finds the smallest element repeatedly in the unsorted part and stacks it at the beginning. Its time complexity is T(n)=O(n2) . I use recurrence in this case, but you can use two nested loops, either. It is quite the same.

#include <stdio.h>

void selectionsort(int arr[], int l, int r){
    if (r >= l){
        int flag = l;
        int i;
        // Find the smallest index 'flag'
        for (i = l + 1; i <= r; i++){
            if (arr[flag] > arr[i]) flag = i;
        }
        // Swap arr[flag] and arr[l]
        int temp = arr[flag];
        arr[flag] = arr[l];
        arr[l] = temp;
        selectionsort(arr, l+1, r);
    }
}

int main(void){
    int j ;
    int arr[] = {1, 5, 3, 2, 9, 7, 6};
    int n = sizeof(arr)/ sizeof(arr[0]);
    selectionsort(arr, 0, n-1);
    for (j = 0; j < n; j++)
        printf("%d\n", arr[j] );
}

Note: Selection sort makes O(n) swaps which is minimum among all sorting algorithms mentioned above.

Bubble sort

Bubble sort is the simplest sorting algorithm. It works by continuously comparing the element with the unsorted sub-part. In the first iteration, it results in a largest or smallest element to be placed in the end or the beginning of an array respectively. Such method is continue on with the unsorted array. Time complexity: T(n)=O(n2) .

#include <stdio.h>
#include "util.h"

void bubbleSort(int arr[], int n){
    int i, j;

    for (i = 0; i < n -1; i++){
        for (j = 0; j < n - i -1; j++){
            if (arr[j] > arr[j+1]) swap(&arr[j], &arr[j+1]);
        }
    }
}

// Driver program to test above functions
int main()
{
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(arr)/sizeof(arr[0]);
    bubbleSort(arr, n);
    printf("Sorted array: \n");
    printArray(arr, n);
    return 0;
}

Insertion sort

Insertion runs by insert an element (from i=1 to i=n ) to the listed left array. Its time complexity is O(n2) .

#include <stdio.h>
#include "util.h"

void insertion_sort(int arr[], int l, int r){
    if( l < r){
        for(int i = 0; i < l; i++){
            /* If arr[i] is larger than the left sorted part*/
            if (arr[i] > arr[l]){
                for(int j = l; j > i; j--) swap(&arr[j], &arr[j-1]);
            }
        }
        insertion_sort(arr, l+1, r);
    }

}

int main(void){
    int arr[] = {1,34,5,21,43,28,17};
    int n = sizeof(arr)/ sizeof(arr[0]);
    insertion_sort(arr, 0, n);
    printArray(arr, n);
    return 0;
}

The algorithm can be optimized by using binary search to find out the from which element that the sub-array is greater than the ith element from ith iteration.

#include <stdio.h>
#include "util.h"


void insertion_sort(int arr[], int length){
    int temp, low, mid, high;
    for (int i = 1; i < length; i++){
        /* sorted subarray: 0 ~ i-1 */
        low = 0;
        temp = arr[i];
        high = i - 1;
        /* Binary search */
        while (low <= high){
            mid = (low + high)/ 2;
            /* If arr[i] is smaller, its location should be on the left of mid */
            if( arr[mid] > temp) high = mid - 1;
            /* If arr[i] is larger, its location should be on the right of mid */
            else low = mid + 1;

        }
        for (int j = i ; j > high; j--)
            arr[j] = arr[j-1];
        arr[high+1] = temp;
    }
}

int main(void){
    int arr[] = {1,34,5,21,43,28,17,2,9,32};
    int n = sizeof(arr)/ sizeof(arr[0]);
    insertion_sort(arr, n);
    printArray(arr, n);
    return 0;
}

Merge sort

Merge sort is a divide and conquer algorithm, it cuts an array into two halves, then sort them and merge them together. Its time complexity is O(nlogn) in 3 cases(worst, best, average) .


#include <stdio.h>
#include "util.h"


void merge(int arr[], int l, int m, int r){
    int n1, n2, i, j;
    /* number of subaray */
    n1 = m - l + 1;
    n2 = r - m;

    int L[n1], R[n2];

    /* Copy two subarrays */
    for (i = 0; i < n1; i++){
        L[i] = arr[l + i];
    }
    for (j = 0; j < n2; j++){
        R[j] = arr[m + j + 1];
    }

    /* i: index of L[], j: index of R[], k: index of arr[] */
    i = 0; j = 0;
    int k = l;
    while (i < n1 && j < n2){

        if (L[i] <= R[j]){
            arr[k] = L[i];
            k++; i++;
        }
        else {
            arr[k] = R[j];
            k++; j++;
        }
    }
    while (i < n1){
        arr[k] = L[i];
        k++; i++;
    }
    while (j < n2){
        arr[k] = R[j];
        k++; j++;
    }
}

void merge_sort(int arr[], int l, int r){

    if (l < r){
        /* Equal to (l+r)/2 */
        int mid = l + (r-l)/ 2;
        merge_sort(arr, l, mid);
        merge_sort(arr, mid+1, r);
        merge(arr, l, mid, r);
    }
}

int main(void){
    int arr[] = {1,34,5,21,43,28,17,12};
    int n = sizeof(arr)/ sizeof(arr[0]);
    merge_sort(arr, 0, n - 1);
    printArray(arr, n);
    return 0;
}

Quick sort

Quick is an algorithm being used widely in actual application. It starts by choose a pivot and place those smaller elements on the left of it and the larger elements on the left of it. It is a divide and conquer algorithm and requires an average time complexity of O(nlogn) .
Note:
1. Quick Sort is preferred over MergeSort for sorting Arrays.
2. MergeSort is preferred over QuickSort for Linked Lists

#include <stdio.h>
#include "util.h"

int partition(int arr[], int left, int right){
    /* Choose the rightest element as pivot */
    int pivot = arr[right];
    int j = left - 1;
    for (int i = left; i < right; i++){
        /* If smaller than pivot, swap it */
        if (arr[i] < pivot){
            j++;
            swap(&arr[j],&arr[i]);
        }
    }
    swap(&arr[right],&arr[j+1]);
    return (j+1) ;
}

void quickSort(int arr[], int left, int right){
   if (left < right){
        int seed = partition(arr, left, right);
        quickSort(arr, left, seed-1);
        quickSort(arr, seed+1, right);
   }
}

int main()
{
    int arr[] = {10, 7, 8, 3, 3, 9, 1, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    quickSort(arr, 0, n-1);
    printf("Sorted array: \n");
    printArray(arr, n);
    return 0;
}

Summary

Worst case complexities:
Merge Sort — nLogn
Bubble Sort — n2
Quick Sort — n2
Selection Sort — n2
Insertion sort – n2

Best case complexities:
Bubble Sort – n
Inserttion Sort – n <script type="math/tex" id="MathJax-Element-16">n</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值