📜  IntroSort 或内省排序(1)

📅  最后修改于: 2023-12-03 15:31:25.691000             🧑  作者: Mango

IntroSort 或内省排序

IntroSort 是一种快速的排序算法,它是快速排序、堆排序和插入排序的混合。

内省排序是其它排序算法的一种优化算法,它是计算机科学中一种排序算法。该算法对于数据量较大、无序度不确定的数据排序避免了快速排序的最坏情况,即退化为类似冒泡排序的时间复杂度。

算法描述

IntroSort 先使用快速排序对输入的数组排序。如果快速排序的深度超过了log_{2}(n) , 会改为使用堆排序。而如果输入数据量小于某个门槛值,采用插入排序。将这些算法结合使用,可以达到较高的效率。

内省排序先使用快排进行排序,但是如果使用快排后递归超过了 log_{2}(n) 次,算法就会将此数组转换为 heap(堆)结构;当递归的数组长度小于等于阈值时,采用插入排序。用这种方法可以避免一般的快排在最坏情况下复杂度退化到 O(n²) 的问题。

算法复杂度

IntroSort 的最坏时间复杂度为 O(nlog(n)),其期望时间复杂度为 O(nlog(n))。

代码实现

以下是 IntroSort 或内省排序的 C++ 实现:

#include<bits/stdc++.h>
using namespace std;
 
int MaxElement(vector<int> &a, int n) {
    int mx = INT_MIN;
    for (int i = 0; i < n; i++) {
        if (a[i] > mx) mx = a[i];
    }
    return mx;
}
 
void InsertionSort(vector<int>& a, int n){
    for (int i = 1; i < n; i++){
        int key = a[i];
        int j = i - 1;
        while (j >= 0 && a[j] > key){
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = key;
    }
}
 
void Heapify(vector<int>& a, int n, int i) {
    int largest = i; // root
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    if (left < n && a[left] > a[largest]) largest = left;
    if (right < n && a[right] > a[largest]) largest = right;
    if (largest != i) {
        swap(a[i], a[largest]);
        Heapify(a, n, largest);
    }
}
 
void HeapSort(vector<int>& a, int n) {
    for (int i = n / 2 - 1; i >= 0; i--) Heapify(a, n , i);
    for (int i = n - 1; i >= 0; i--) {
        swap(a[0], a[i]);
        Heapify(a, i, 0);
    }
}
 
void QuickSort(vector<int>& a, int n) {
    sort(a.begin(), a.end());
}
 
void IntroSort(vector<int>& a, int n, int depth) {
    if (n == 0) return;
    if (depth == 0) return HeapSort(a, n); // Once the depth is 0, then change to Heap Sort algorithm.
    else depth--;
    if (n < 16){
        InsertionSort(a, n);
        return;
    }
    int pivot = rand() % n;
    int temp;
    temp = a[pivot]; a[pivot] = a[n - 1]; a[n - 1] = temp;
    int l = 0, r = n - 1;
    while (l < r) {
        if (a[l] < a[n - 1]) l++;
        else if (l != r--) swap(a[l], a[r + 1]);
    }
    temp = a[l]; a[l] = a[n - 1]; a[n - 1] = temp;
    IntroSort(a, l, depth);
    IntroSort(a + r + 1, n - r - 1, depth);
}
 
void PrintArray(vector<int>& a, int n){
    cout << "The result array is : \n";
    for (int i = 0; i < n; i++) cout << a[i] << " ";
}
 
int main(){
    int n;
    vector<int> a;
    cout << "Please input the number of elements: ";
    cin >> n;
    cout << "Please input the n elements one by one: ";
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        a.push_back(x);
    }
    int depth = (int)log2(n);
    IntroSort(a, n, depth);
    PrintArray(a, n);
    return 0;
}

上述代码实现了 IntroSort 或内省排序的功能。