三向快速排序需要更高的性能

时间:2016-03-31 10:48:28

标签: c++ algorithm performance time quicksort

我目前正在尝试实现三分区快速排序。下面的代码工作正常,但没有足够的时间运行。我对数据结构,算法以及一般的“深入”编程都很陌生,所以我试图摆弄它以使其在更短的时间内工作,这在很大程度上已经没有了。 (记忆表现很好。)

我的直觉是改变枢轴,但我担心它不会是一个三向快速排序。

#include <iostream>
#include <vector>
#include <cstdlib>

using std::vector;
using std::swap;


int partition3(vector<int> &a, int l, int r) {

    int x = a[l]; 
    int j = l;
    int k = r;
    int i = l+1; 

    while (i <= k) {
        if (a[i] < x) {
          swap(a[i],a[j]);
          j++; 
          i++;
        }
        else if(a[i] > x) {
            swap(a[i],a[k]);
            k--;
        }
        else {
            i++;
        }
    }

    return j;
}

void randomized_quick_sort(vector<int> &a, int l, int r) {

    if (l >= r) {
        return;
    }

    int k = l + rand() % (r - l + 1);
    swap(a[l], a[k]);

    while (l < r) {
        int m = partition3(a, l, r);
        if ((m-l) < (r-m)) {
            randomized_quick_sort(a, l, m - 1);
            l = m + 1; 
        }
        else {
            randomized_quick_sort(a, m + 1, r);
            r = m - 1;
        }
    }
}

int main() {
    int n; 
    std::cin >> n;
    vector<int> a(n);
    for (size_t i = 0; i < a.size(); ++i) {
        std::cin >> a[i];
    }
    randomized_quick_sort(a, 0, a.size() - 1);
    for (size_t i = 0; i < a.size(); ++i) {
        std::cout << a[i] << ' ';
    }
}

2 个答案:

答案 0 :(得分:4)

在现实世界中,排序是一个非常复杂的问题。尝试查看一些有效的实现,例如,由C ++标准库的实现提供的实现。浏览网页,阅读文章,查看讨论,......

只是一些注释:

  1. 随机数生成(相对)昂贵,它可以显着减慢快速排序。 (但是,对于某种数据,它也可以做相反的事情。)
  2. 整数除法(相对)非常昂贵,可能比随机数生成更多。
  3. 在实践中很少使用Pure quicksort。通常,它与插入排序相结合,因为递归调用对于非常小的分区来说效率低(阈值通常设置在8到16个元素之间)。
  4. 为了防止快速排序最坏情况的复杂性,通常会检查递归级别,如果它超过某个阈值(2 x log_2(n)),则其余数据会被另一个算法(通常为heapsort)所支持。
  5. 等等...

    <强>更新

    还有两个想法:

    1. 在多核/多核环境中,并行算法可能会为您提供最佳加速。但设计并行快速排序绝非易事。大部分复杂性落在有效的并行分区和负载平衡上。 Libstdc ++ Parallel Mode有一个很好的OpenMP实现。或者,您也可以查看我的AQsort:https://github.com/DanielLangr/AQsort
    2. 要使quicksort更有效,请使用尾部调用消除/优化。它大大减少了所需的调用堆栈空间。

答案 1 :(得分:0)

我在这里看到非常可靠的代码。

如果要保留算法,加速算法的最佳方法是将其从递归更改为迭代。它不会是一个巨大的推动,但它会有所帮助,每个功能调用是一个很好的避免开销。手动交换也是一个不错的选择。

你也可以获得一些速度来避免额外的内存分配,所以你应该尝试尽可能多地重用你的变量,例如,在一段时间内声明int。