This article will introduce common sorting algorithms (implemented in C++)

1. Bubble sort

Divides an array into ordered (left) and unordered (right) regions. The ordered region is empty at initialization and the unordered region contains all the elements of the array

Start with the last element of the unordered region each time and bubble forward to the first location of the unordered region to make it orderly

template<typename E>
void swap(E A[], int i, int j) {
    E temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

template<typename E>
void bubbleSort(E A[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = n - 1; j > i; j--) {
            if (A[j] < A[j - 1]) {
                swap(A, j, j - 1); }}}}Copy the code

2. Selection sort

Divides an array into ordered (left) and unordered (right) regions. The ordered region is empty at initialization and the unordered region contains all the elements of the array

Each time, select an appropriate element from the unordered region and swap it to the first position in the unordered region to make it orderly

template<typename E>
void swap(E A[], int i, int j) {
    E temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

template<typename E>
void selectionSort(E A[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int minIdx = i;
        for (int j = i; j <= n - 1; j++) {
            if (A[j] < A[minIdx]) minIdx = j;
        }
        swap(A, i, minIdx); }}Copy the code

3. Insert sort

An array is divided into ordered (left) and unordered (right) regions, with the ordered containing the first element and the unordered containing the rest of the array at initialization

Each time, swap the first element in the unordered region all the way forward to the appropriate position in the ordered region, so that it becomes ordered

template<typename E>
void swap(E A[], int i, int j) {
    E temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

template<typename E>
void insertionSort(E A[], int n) {
    for (int i = 1; i < n; i++) {
		for (int j = i; j > 0; j--) {
            if (A[j] < A[j - 1]) {
                swap(A, j, j - 1); }}}}Copy the code

4. Merge sort

This is done recursively, splitting the array in two at a time, sorting the two arrays separately, and merging the two arrays

template<typename E>
void mergeSort(E A[], E T[], int l, int r) {
    if (l == r) return;
    int m = (l + r) / 2;
    mergeSort<E>(A, T, l, m);
    mergeSort<E>(A, T, m + 1, r);
    // merge
    for (int k = l; k <= r; k++) T[k] = A[k];
    int i = l, j = m + 1;
    for (int c = l; c <= r; c++) {
        if (i > m) A[c] = T[j++];
        else if (j > r) A[c] = T[i++];
        else if (T[i] < T[j]) A[c] = T[i++];
        elseA[c] = T[j++]; }}Copy the code

Optimization: Insert the back half of the temporary array backwards so that you don’t have to detect bounds

template<typename E>
void mergeSort(E A[], E T[], int l, int r) {
    if (l == r) return;
    int m = (l + r) / 2;
    mergeSort<E>(A, T, l, m);
    mergeSort<E>(A, T, m + 1, r);
    // merge
    for (int k = l; k <= m; k++) T[k] = A[k];
    for (int k = 1; k <= r - m; k++) T[r - k + 1] = A[k + m];
    int i = l, j = r;
    for (int c = l; c <= r; c++) {
        if (T[i] < T[j]) A[c] = T[i++];
        elseA[c] = T[j--]; }}Copy the code

5. Quicksort

Recursively, each time in the array to select a baseline, according to the baseline array divided into two, and then the two arrays sorted separately, splice two arrays

template<typename E>
void swap(E A[], int i, int j) {
    E temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

template<typename E>
void quickSort(E A[], int l, int r) {
    if (r <= l) return;
    // find pivot
    int pivotIndex = (l + r) / 2;
    E pivot = A[pivotIndex];
    // put pivot at last
    swap(A, pivotIndex, r);
    // partition
    int i = l - 1;
    int j = r;
    do {
        while (A[++i] < pivot) {}
        while (i < j && pivot < A[--j]) {}
        swap(A, i, j);
    } while (i < j);
    // put pivot in place
    swap(A, r, i);
    // recursive
    quickSort(A, l, i - 1);
    quickSort(A, i + 1, r);
}
Copy the code

Optimization: Use stacks instead of recursion

template<typename E>
void swap(E A[], int i, int j) {
    E temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

template<typename E>
void quickSort(E A[], int l, int r) {
    int stack[200];
    int top = - 1;
    stack[++top] = l;
    stack[++top] = r;
    while (top > 0) {
        // pop the stack
        r = stack[top--];
        l = stack[top--];
        // find pivot
        int pivotIndex = (l + r) / 2;
        E pivot = A[pivotIndex];
        // put pivot at last
        swap(A, pivotIndex, r);
        // partition
        int i = l - 1;
        int j = r;
        do {
            while (A[++i] < pivot) {}
            while (i < j && pivot < A[--j]) {}
            swap(A, i, j);
        } while (i < j);
        // undo the last swap
        swap(A, i, j);
        // put pivot in place
        swap(A, r, i);
        // load up stack
        if (i - 1 > l) {
            stack[++top] = l;
            stack[++top] = i - 1;
        }
        if (r > i + 1) {
            stack[++top] = i + 1; stack[++top] = r; }}}Copy the code

6, test,

The test program

#include <iostream>
#include <time.h>
using namespace std;

int main(a) {
    const int num = 1000;
    const int minVal = 0;
    const int maxVal = 1000;
    int* arr = new int[num];
    for (int i = 0; i < num; i++)
        arr[i] = rand() % (maxVal - minVal + 1) + minVal;
    
    int* a4b = new int[num];
    int* a4s = new int[num];
    int* a4i = new int[num];
    int* a4m = new int[num];
    int* a4q = new int[num];

    int* t = new int[num];

    for (int i = 0; i < num; i++) a4b[i] = arr[i];
    for (int i = 0; i < num; i++) a4s[i] = arr[i];
    for (int i = 0; i < num; i++) a4i[i] = arr[i];
    for (int i = 0; i < num; i++) a4m[i] = arr[i];
    for (int i = 0; i < num; i++) a4q[i] = arr[i];

    clock_t start, end;

    start = clock(a);bubbleSort(a4b, num);
    end = clock(a); cout <<"bubbleSort: "< < (double)(end-start)/CLOCKS_PER_SEC << endl;
    
    start = clock(a);selectionSort(a4s, num);
    end = clock(a); cout <<"selectionSort: "< < (double)(end-start)/CLOCKS_PER_SEC << endl;

    start = clock(a);insertionSort(a4i, num);
    end = clock(a); cout <<"insertionSort: "< < (double)(end-start)/CLOCKS_PER_SEC << endl;

    start = clock(a);mergeSort(a4m, t, 0, num - 1);
    end = clock(a); cout <<"mergeSort: "< < (double)(end-start)/CLOCKS_PER_SEC << endl;

    start = clock(a);quickSort(a4q, 0, num - 1);
    end = clock(a); cout <<"quickSort: "< < (double)(end-start)/CLOCKS_PER_SEC << endl;

    return 0;
}
Copy the code

The test results

The data size 1000 10000 100000 1000000 10000000 100000000
bubble sort 0.003 s 0.355 s 41.414 s / / /
selection sort 0.001 s 0.123 s 12.151 s / / /
insertion sort 0.002 s 0.224 s 22.881 s / / /
merge sort 0 s 0.002 s 0.021 s 0.212 s 2.285 s 24.352 s
quick sort 0 s 0.002 s 0.017 s 0.175 s 1.826 s 19.498 s