partial_sort_copy是最快的C++部分排序吗
Is partial_sort_copy the fastest C++ partial sort?
考虑以下函数median
:
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;
}
我使用部分排序来降低复杂性,因为我只需要对列表的一半进行排序。
此外,我假设std::partial_sort_copy
比std::partial_sort
或std::nth_element
快,因为在排序算法中不需要混洗(It1!=It2)。我的假设正确吗?
注意:假设real_t
可以是double
,所以请不要批评除法的使用。
NBB:我用的是-pedantic
,vars
的长度不超过15个元素。
使用以下代码
#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");
}
我得到以下结果:
std::sort: 141
std::partial_sort: 359
std::partial_sort_copy: 831
std::nth_element: 149
在AMD Phenom II x4 2.5GHz上使用Visual Studio 2013以64位发布模式进行测试。
如果可以的话,我会选择部分快速排序。
部分快速分拣信息
但如果你只需要比较这两个。。。则部分排序比部分排序复制更好。这里你有更多关于这两种方法的信息:
部分分拣信息
部分分拣复制信息
在这里,您还可以找到Partial Quicksort的算法代码示例-它是在C和matlab中实现的:
示例-部分快速排序
您测试过代码吗?
std::partial_sort_copy(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];
}
注意,如果给定initializer_list
作为数据源,那么像nth_element
或partial_sort
这样的就地修改算法将不起作用,因为初始化器列表无法修改(无论参数是否标记为const
,initializer_list
中的迭代器都是const
限定的)。因此,必须使用标准算法函数进行复制以找到中值,方法是在调用算法之前复制列表,或者使用作为其工作一部分执行复制的算法变体,如partial_sort_copy()
。
- 二叉排序树无法编译
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- C++选择排序算法中的逻辑错误
- 使用C++程序合并排序没有得到正确的输出
- 计算排序向量的向量中唯一值的计数
- 排序算法c++
- 使用2个键的cpp-stl::优先级队列排序不正确
- 将结构向量排序为子组
- 在c++中尝试对对象数组进行排序时,出现std:bad_alloc错误
- 如何对点云数据进行排序
- 对字符串进行排序时,在c++中处理sort()
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 下面是排序算法O(n)吗
- std::sort()函数无法对向量的一部分进行排序
- shell排序中的交换和比较
- clang格式:禁用排序包含
- 显示错误输出的简单数组排序程序
- 为什么我的排序算法会更改数组值
- 试图在c++中对数字列表进行排序
- 如何在C++中对数组进行冒泡排序