Implementation of the top ten sorting algorithms (C/C++)

The following is a simple C++ implementation of the top ten classic sorting algorithms:

  1. Bubble Sort:
  • Idea: Repeatedly iterate through the list to be sorted, compare two adjacent elements, and swap them if they are in the wrong order.
  • Time complexity: Worst case and average case are O(n^2), best case is O(n).
void bubbleSort(int arr[], int size) {
    
    
    for (int i = 0; i < size-1; i++) {
    
    
        for (int j = 0; j < size-i-1; j++) {
    
    
            if (arr[j] > arr[j+1]) {
    
    
                std::swap(arr[j], arr[j+1]);
            }
        }
    }
}
  1. Selection Sort:
  • Idea: Split the array into two parts, sorted and unsorted, and each time select the smallest (or largest) element from the unsorted part and put it at the end of the sorted part.
  • Time complexity: Worst case, average case, and best case are all O(n^2).
void selectionSort(int arr[], int size) {
    
    
    for (int i = 0; i < size-1; i++) {
    
    
        int minIdx = i;
        for (int j = i+1; j < size; j++) {
    
    
            if (arr[j] < arr[minIdx]) {
    
    
                minIdx = j;
            }
        }
        std::swap(arr[i], arr[minIdx]);
    }
}
  1. Insertion Sort:
  • Idea: Divide the array into two parts, sorted and unsorted, and select an element from the unsorted part each time to insert it into the appropriate position of the sorted part.
  • Time complexity: Worst case and average case are O(n^2), best case is O(n).
void insertionSort(int arr[], int size) {
    
    
    for (int i = 1; i < size; i++) {
    
    
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
    
    
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}
  1. Shell Sort:
  • Idea: An improvement on insertion sort, by dividing the data into multiple small blocks and performing insertion sort separately, and then gradually increasing the size of the blocks.
  • Time complexity: Depending on the interval sequence chosen, the best interval sequence time complexity is O(n log^2 n).
void shellSort(int arr[], int size) {
    
    
    for (int gap = size/2; gap > 0; gap /= 2) {
    
    
        for (int i = gap; i < size; i++) {
    
    
            int temp = arr[i];
            int j;
            for (j = i; j >= gap && arr[j-gap] > temp; j -= gap) {
    
    
                arr[j] = arr[j-gap];
            }
            arr[j] = temp;
        }
    }
}
  1. Merge Sort:
  • Idea: Merge sort is a divide-and-conquer algorithm that decomposes a large problem into small problems, solves the small problems, and then merges their solutions into an overall solution.

step:

  1. Split the array in half and merge sort each half recursively.
  2. Merge two sorted subarrays into one sorted array.
  • Time complexity: always O(nlogn), suitable for large data sets.
void merge(int arr[], int left, int mid, int right) {
    
    
    int i, j, k;
    int n1 = mid - left + 1;
    int n2 = right - mid;
    
    int L[n1], R[n2];
    
    for (i = 0; i < n1; i++)
        L[i] = arr[left + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[mid + 1 + j];
    
    i = 0;
    j = 0;
    k = left;
    
    while (i < n1 && j < n2) {
    
    
        if (L[i] <= R[j]) {
    
    
            arr[k] = L[i];
            i++;
        } else {
    
    
            arr[k] = R[j];
            j++;
        }
        k++;
    }
    
    while (i < n1) {
    
    
        arr[k] = L[i];
        i++;
        k++;
    }
    
    while (j < n2) {
    
    
        arr[k] = R[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);
    }
}
  1. Quick Sort:
  • Idea: Use the divide-and-conquer strategy to divide the array into two parts by selecting a benchmark element, placing the one smaller than the benchmark on the left, and the one larger than the benchmark on the right, and then recursively sort the left and right parts.
  • Time complexity: The worst case is O(n^2), the average case is O(n log n), and the best case is O(n log n).
#include <iostream>
#include <vector>

int partition(std::vector<int>& arr, int low, int high) {
    
    
    int pivot = arr[high];  // 选择最后一个元素作为基准值
    int i = low - 1;  // i 是小于基准值的元素的最右位置(即i和i左边下标的元素都小于基准值)
    
    for (int j = low; j <= high - 1; j++) {
    
    
        if (arr[j] <= pivot) {
    
    
            i++;
            std::swap(arr[i], arr[j]);  // 将小于基准值的元素放到 i 的位置
        }
    }
    std::swap(arr[i + 1], arr[high]);  // 将基准值放到正确的位置
    return i + 1;
}

void quickSort(std::vector<int>& arr, int low, int high) {
    
    
    if (low < high) {
    
    
        int pi = partition(arr, low, high);  // 分割数组
        quickSort(arr, low, pi - 1);  // 对左半部分进行递归排序
        quickSort(arr, pi + 1, high);  // 对右半部分进行递归排序
    }
}
  1. Heap Sort:
  • Idea: Treat the array as a binary heap, use the properties of the heap to put the largest (or smallest) element at the end of the heap, then re-adjust the heap, and repeat this process until the entire array is sorted.
  • Time complexity: always O(n log n) and does not depend on the initial state of the input data.
void heapify(int arr[], int size, int i) {
    
    
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    
    if (left < size && arr[left] > arr[largest])
        largest = left;
    
    if (right < size && arr[right] > arr[largest])
        largest = right;
    
    if (largest != i) {
    
    
        std::swap(arr[i], arr[largest]);
        heapify(arr, size, largest);
    }
}

void heapSort(int arr[], int size) {
    
    
    for (int i = size / 2 - 1; i >= 0; i--)
        heapify(arr, size, i);
    
    for (int i = size - 1; i >= 0; i--) {
    
    
        std::swap(arr[0], arr[i]);
        heapify(arr, i, 0);
    }
}
  1. Counting Sort:
  • Idea: It is suitable for integer sorting within a certain range, by counting the number of occurrences of each element, and then sorting according to the statistical information.
  • Time complexity: The best case is O(n+k), where k is the data range, but it does not apply to negative numbers and floating point numbers.
void countingSort(int arr[], int size) {
    
    
    int max = arr[0], min = arr[0];
    for (int i = 1; i < size; i++) {
    
    
        if (arr[i] > max)
            max = arr[i];
        if (arr[i] < min)
            min = arr[i];
    }
    
    int range = max - min + 1;
    int* count = new int[range]();
    int* output = new int[size];
    
    for (int i = 0; i < size; i++)
        count[arr[i] - min]++;
    
    for (int i = 1; i < range; i++)
        count[i] += count[i - 1];
    
    for (int i = size - 1; i >= 0; i--) {
    
    
        output[count[arr[i] - min] - 1] = arr[i];
        count[arr[i] - min]--;
    }
    
    for (int i = 0; i < size; i++)
        arr[i] = output[i];
    
    delete[] count;
    delete[] output;
}
  1. Bucket Sort:
  • Idea: Divide the data into a limited number of buckets, and then sort each bucket separately.
  • Time complexity: Depends on the number of buckets and the algorithm for sorting inside the buckets, usually O(n+k), where k is the number of buckets.
void bucketSort(int arr[], int size) {
    
    
    const int max = *std::max_element(arr, arr + size);
    const int min = *std::min_element(arr, arr + size);
    const int range = max - min + 1;
    
    std::vector<std::vector<int>> buckets(range);
    
    for (int i = 0; i < size; i++) {
    
    
        int index = (arr[i] - min) * range / (max - min + 1);
        buckets[index].push_back(arr[i]);
    }
    
    int idx = 0;
    for (int i = 0; i < range; i++) {
    
    
        std::sort(buckets[i].begin(), buckets[i].end());
        for (int j = 0; j < buckets[i].size(); j++) {
    
    
            arr[idx++] = buckets[i][j];
        }
    }
}
  1. Radix Sort:
  • Idea: Sort the data by digits, starting from the lowest bit and going to the highest bit.
  • Time complexity: O(n*k), where n is the number of elements and k is the number of digits in the element.
int getMax(int arr[], int size) {
    
    
    int max = arr[0];
    for (int i = 1; i < size; i++) {
    
    
        if (arr[i] > max)
            max = arr[i];
    }
    return max;
}

void countSort(int arr[], int size, int exp) {
    
    
    int output[size];
    int count[10] = {
    
    0};
    
    for (int i = 0; i < size; i++)
        count[(arr[i] / exp) % 10]++;
    
    for (int i = 1; i < 10; i++)
        count[i] += count[i - 1];
    
    for (int i = size - 1; i >= 0; i--) {
    
    
        output[count[(arr[i] / exp) % 10] - 1] = arr[i];
        count[(arr[i] / exp) % 10]--;
    }
    
    for (int i = 0; i < size; i++)
        arr[i] = output[i];
}

void radixSort(int arr[], int size) {
    
    
    int max = getMax(arr, size);
    
    for (int exp = 1; max / exp > 0; exp *= 10)
        countSort(arr, size, exp);
}

Guess you like

Origin blog.csdn.net/weixin_36313227/article/details/133267346