Implementierung der zehn besten Sortieralgorithmen (C/C++)

Das Folgende ist eine einfache C++-Implementierung der zehn besten klassischen Sortieralgorithmen:

  1. Blasensortierung:
  • Idee: Wiederholt die zu sortierende Liste durchlaufen, zwei benachbarte Elemente vergleichen und sie austauschen, wenn sie in der falschen Reihenfolge sind.
  • Zeitkomplexität: Worst Case und Average Case sind O(n^2), Best Case ist 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. Auswahlsortierung:
  • Idee: Teilen Sie das Array in zwei Teile auf, sortiert und unsortiert, und wählen Sie jedes Mal das kleinste (oder größte) Element aus dem unsortierten Teil aus und platzieren Sie es am Ende des sortierten Teils.
  • Zeitkomplexität: Worst Case, Average Case und Best Case sind alle 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. Sortieren durch Einfügen:
  • Idee: Teilen Sie das Array in zwei Teile, sortiert und unsortiert, und wählen Sie jedes Mal ein Element aus dem unsortierten Teil aus, um es an der entsprechenden Position des sortierten Teils einzufügen.
  • Zeitkomplexität: Worst Case und Average Case sind O(n^2), Best Case ist 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. Muschelsortierung:
  • Idee: Eine Verbesserung der Einfügungssortierung, indem die Daten in mehrere kleine Blöcke aufgeteilt werden und die Einfügungssortierung separat durchgeführt wird und dann die Größe der Blöcke schrittweise erhöht wird.
  • Zeitkomplexität: Abhängig von der gewählten Intervallsequenz ist die beste Zeitkomplexität der Intervallsequenz 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. Zusammenführen, sortieren:
  • Idee: Merge Sort ist ein Divide-and-Conquer-Algorithmus, der ein großes Problem in kleine Probleme zerlegt, die kleinen Probleme löst und dann ihre Lösungen zu einer Gesamtlösung zusammenführt.

Schritt:

  1. Teilen Sie das Array in zwei Hälften und sortieren Sie jede Hälfte rekursiv.
  2. Füge zwei sortierte Unterarrays zu einem sortierten Array zusammen.
  • Zeitkomplexität: immer O(nlogn), geeignet für große Datenmengen.
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. Schnelle Sorte:
  • Idee: Verwenden Sie die Divide-and-Conquer-Strategie, um das Array in zwei Teile zu teilen, indem Sie ein Benchmark-Element auswählen, das Element, das kleiner als der Benchmark ist, links und das Element, das größer als der Benchmark ist, rechts platzieren und diese dann rekursiv sortieren linke und rechte Teile.
  • Zeitkomplexität: Der schlechteste Fall ist O(n^2), der durchschnittliche Fall ist O(n log n) und der beste Fall ist 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-Sortierung:
  • Idee: Behandeln Sie das Array als binären Heap, verwenden Sie die Eigenschaften des Heaps, um das größte (oder kleinste) Element am Ende des Heaps zu platzieren, passen Sie dann den Heap neu an und wiederholen Sie diesen Vorgang, bis das gesamte Array sortiert ist.
  • Zeitkomplexität: immer O(n log n) und hängt nicht vom Anfangszustand der Eingabedaten ab.
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. Zählsortierung:
  • Idee: Es eignet sich für die Ganzzahlsortierung innerhalb eines bestimmten Bereichs, indem die Anzahl der Vorkommen jedes Elements gezählt und dann anhand der statistischen Informationen sortiert wird.
  • Zeitkomplexität: Der beste Fall ist O(n+k), wobei k der Datenbereich ist, dies gilt jedoch nicht für negative Zahlen und Gleitkommazahlen.
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. Eimersortierung:
  • Idee: Teilen Sie die Daten in eine begrenzte Anzahl von Buckets auf und sortieren Sie dann jeden Bucket separat.
  • Zeitkomplexität: Hängt von der Anzahl der Buckets und dem Algorithmus zum Sortieren innerhalb der Buckets ab, normalerweise O(n+k), wobei k die Anzahl der Buckets ist.
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-Sortierung:
  • Idee: Sortieren Sie die Daten nach Ziffern, beginnend beim niedrigsten Bit bis zum höchsten Bit.
  • Zeitkomplexität: O(n*k), wobei n die Anzahl der Elemente und k die Anzahl der Ziffern im Element ist.
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);
}

Supongo que te gusta

Origin blog.csdn.net/weixin_36313227/article/details/133267346
Recomendado
Clasificación