Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 部分排序拷贝是最快的C++;部分排序?_C++_Sorting - Fatal编程技术网

C++ 部分排序拷贝是最快的C++;部分排序?

C++ 部分排序拷贝是最快的C++;部分排序?,c++,sorting,C++,Sorting,考虑以下函数,中值: real_t median(const std::initializer_list<real_t> vars) { real_t tmp[15]; const unsigned x = vars.size() / 2; if (x & 1) { std::partial_sort_copy(vars.begin(), vars.end(), &tmp[0], &tmp[x]); retu

考虑以下函数,
中值

  real_t median(const std::initializer_list<real_t> vars) {
    real_t tmp[15];
    const unsigned x = vars.size() / 2;
    if (x & 1) {
      std::partial_sort_copy(vars.begin(), vars.end(), &tmp[0], &tmp[x]);
      return tmp[x];
    }
    const unsigned y = x + 1;
    std::partial_sort_copy(vars.begin(), vars.end(), &tmp[0], &tmp[y]);
    return (tmp[x] + tmp[y]) / 2;
  }
real\u t median(const std::initializer\u list vars){
real_t tmp[15];
const unsigned x=vars.size()/2;
如果(x&1){
std::partial_sort_copy(vars.begin()、vars.end()、&tmp[0]、&tmp[x]);
返回tmp[x];
}
常数无符号y=x+1;
std::部分排序拷贝(vars.begin()、vars.end()、&tmp[0]、&tmp[y]);
返回(tmp[x]+tmp[y])/2;
}
我使用部分排序来降低复杂性,因为我只需要对列表的一半进行排序

此外,我假设
std::partial_sort\u copy
std::partial_sort
std::nth_元素
更快,因为排序算法中不需要混洗(It1!=It2)。我的假设正确吗


注意:假设
real\u t
可能是一个
double
,所以请不要批评除法的使用


NBB:我使用的是
-pedantic
变量的长度不超过15个元素。

如果我可以选择,我会选择部分快速排序

但是如果你只需要比较这两个。。。那么部分排序比部分排序拷贝更好。以下是关于这两种方法的更多信息:

在这里,您还可以找到部分快速排序的算法代码示例-它是用C和matlab实现的:


使用以下代码

#include <chrono>
#include <iostream>
#include <thread>
#include <string>
#include <array>
#include <algorithm>

volatile int answer;

const int size = 15;

std::array<std::array<int, size>, 0x100> fresh_data;
std::array<std::array<int, size>, 0x100> data;

void naive(int n) {
    auto & a = data[n];
    std::sort(a.begin(), a.end());
    answer = a[size / 2];
}

void fancy(int n) {
    auto & a = data[n];
    std::partial_sort(a.begin(), a.begin() + (size / 2 + 1), a.end());
    answer = a[size / 2 ];
}

void ghoul(int n) {
    auto & a = data[n];
    std::array<int, size / 2 + 1> temp;
    std::partial_sort_copy(a.begin(), a.end(), temp.begin(), temp.end());
    answer = temp[size / 2];

}

void nthel(int n) {
    auto & a = data[n];
    std::nth_element(a.begin(), a.begin() + size / 2, a.end());
    answer = a[size / 2];
}

void gen_data() {
    for (auto & a : fresh_data)
    for (auto & b : a)
        b = rand();
}

void regen_data() {
    data = fresh_data;
}


template <typename T>
void test(T f, std::string n) {
    regen_data();
    auto a = std::chrono::high_resolution_clock::now();
    for (auto i = 0; i < 10000; ++i)
    for (auto i = 0; i < 0x100; ++i)
        f(i);
    auto b = std::chrono::high_resolution_clock::now();
    std::cout << n << ": " << std::chrono::duration_cast<std::chrono::milliseconds>(b - a).count() << std::endl;
}

int main() {
    gen_data();
    test(naive, "             std::sort");
    test(fancy, "     std::partial_sort");
    test(ghoul, "std::partial_sort_copy");
    test(nthel, "      std::nth_element");
}

在AMD Phenom II x4 2.5GHz上以64位发布模式使用Visual Studio 2013进行测试。

您测试过代码吗

std::部分排序拷贝(vars.begin()、vars.end()、&tmp[0]、&tmp[x])
不会将任何内容复制到
tmp[x]
,因为
&tmp[x]
被视为半开放范围的结束(即,它刚刚超过最后一个有效元素)。因此,您的
return
语句访问不确定或默认构造的数组元素

请尝试以下操作:

real_t median(const std::initializer_list<real_t> vars) 
{
    real_t tmp[15];

    size_t siz = vars.size();
    if ((siz == 0) || (15 < siz)) return 0;     // or throw some sort of exception or ???

    const unsigned x = vars.size() / 2;
    std::partial_sort_copy(vars.begin(), vars.end(), &tmp[0], &tmp[x+1]);

    if (siz % 2 == 0) {
        return (tmp[x-1] + tmp[x]) / 2;
    }

    return tmp[x];
}
real\u t median(const std::initializer\u list vars)
{
real_t tmp[15];
size_t siz=vars.size();
如果((siz==0)| |(15

请注意,如果给定一个
初始值设定项列表
作为数据源,则诸如
第n个元素
部分排序
之类的就地修改算法将不起作用,因为无法修改初始值设定项列表(无论参数是否标记为
const
,进入
初始值设定项列表的迭代器都是
const
合格的)因此,必须使用标准算法函数进行复制以找到中值,方法是在调用算法之前复制列表,或者使用执行复制作为其工作一部分的算法变量,例如
partial\u sort\u copy()

你可以尝试其他的方法,看看这个Q+A应该仍然存在于互联网上的某个地方,其他人可以找到。不管我最终是否需要自己对它们进行基准测试并找出答案,我们都会看到。当然,你会意识到,对于仅仅15个元素,甚至对整个列表进行气泡排序就足够了……首先,你可以测试它。Dif不同的实现有不同的速度。第二,
n元素
的渐进复杂性是线性的,而其他两个元素是线性的。第三,
partial\u sort\u copy
需要分配内存和复制元素,因此速度可能较慢。
partial\u sort\u copy
在这个问题上投入了更多内存,但这是一个双刃剑d、 如果CPU缓存溢出,则较大的工作集会降低性能。为了便于使用,这些幻灯片有点复杂。它是否有标准的库实现?w.r.t您的编辑,我得到的印象是,对于较大的工作集,std::nth_元素实际上比这两个元素都快,因为它标榜
O(n)
complexity而不是
Onlog(m)
。刚刚添加了一个链接,其中包含部分快速排序的实现示例-请看一看。请记住std::nth_元素将是O(N*N)而不是O(N)最坏情况下的复杂性。是什么让您相信这一快速排序比任何
std::partial_sort
实现都要快?
partial_sort
允许使用快速排序,但通常不允许,因为一般认为其他算法的平均速度更快。就标准库而言,这实际上是基准在Mavericks上gcc/clang xcode5的数字:
std::sort
:126
std::partial_sort
:1278
std::partial_sort_copy
:2486
std::nth_元素
:260在4种方法测试中的3种方法中,该基准测试是否有点不公平d修改其输入(待排序),它们在随后的迭代中从中受益?我刚刚测试了两种变体—一种是在1000000个随机数组上使用1次迭代,而不是在相同的256个数组上使用10000次迭代;另一种是,所讨论的3次迭代复制了输入数组,而不是引用。在这两种情况下,性能差距都比原始阵列小得多基准测试,但事实上相对排名非常相似。另外,FWIW,在中等数组大小(如1000)下,
n_元素
在允许和不允许输入突变时都要快得多。不,我还没有测试过。这是出生前优化;)谢谢你的回答,这非常有用。
real_t median(const std::initializer_list<real_t> vars) 
{
    real_t tmp[15];

    size_t siz = vars.size();
    if ((siz == 0) || (15 < siz)) return 0;     // or throw some sort of exception or ???

    const unsigned x = vars.size() / 2;
    std::partial_sort_copy(vars.begin(), vars.end(), &tmp[0], &tmp[x+1]);

    if (siz % 2 == 0) {
        return (tmp[x-1] + tmp[x]) / 2;
    }

    return tmp[x];
}