我有一个包含三个浮点值的数组,我想按升序对它们进行排序(尽管可能很容易逆转任何排序算法的顺序)。调用std :: sort似乎有点过分了:
float values[3] = {...};
std::sort(values, values + 3);
您可以执行以下操作:
float sorted[3] = {min(values), values[0] + values[1] + values[2] -
min(values) - max(values), max(values)};
但这看起来很丑陋。添加和减去数字也可以改变中间排序元素的值。并且它不容易就地工作。 同样有趣:
float sorted[3];
/*for(int i = 0; i < 3; ++ i) { // unroll
sorted[(values[i] > values[0]) + (values[i] > values[1]) +
(values[i] > values[2])] = values[i];
}*/ // this is broken, does not work if two or all values are equal
sorted[(values[0] > values[1]) + (values[0] > values[2])] = values[0];
sorted[(values[1] >= values[0]) + (values[1] > values[2])] = values[1];
sorted[(values[2] >= values[0]) + (values[2] >= values[1])] = values[2];
但这种情况取决于比较结果如何转换为整数(可能是比较+标志加载指令)。还取决于编译器如何优化每个元素与其自身的比较,如果考虑特殊的浮点值,这并不容易。也不适用。
#define cswap(a,b) do { if(a > b) { float tmp = a; a = b; b = tmp; } } while(0)
cswap(values[0], values[1]);
cswap(values[1], values[2]);
cswap(values[0], values[1]);
可能有一个排序网络,但我认为除了两个元素的权力之外,它不是最佳的排序。只有三个元素......似乎应该有一个非常简单的方法,但也许没有。
对三个数字进行排序的最小和同时快速的方法是什么?可读性不是一个问题。
这有点类似于Fastest sort of fixed length 6 int array但是在这里我会期待一些简短而快速的代码,因为排序3的值可能用比任意数量项的排序循环更少的代码行编写。
结果:
根据英特尔酷睿i7-2620M和Windows 7上的100亿个数字进行测量。发布时,使用rand()生成数字,但是减去了内部花费的时间。
std::sort method: 3.510 sec
min/max method: 2.964 sec
comparison insertion: 2.091 sec (the fixed version, 2.292 for the buggy one)
sort3() by Jarod42: 1.966 sec
sorting network: 1.903 sec
答案 0 :(得分:9)
一般算法是:
if (a[0] > a[1])
swap(a[0], a[1]);
if (a[0] > a[2])
swap(a[0], a[2]);
if (a[1] > a[2])
swap(a[1], a[2]);
答案 1 :(得分:3)
只有6种可能的排列,所以你可以只写一堆嵌套条件来获得所有可能性。例如,见here。另一方面,像insertion sort这样简单但更通用的东西对于小数组是有效的。插入排序也用作optimization for sorting smaller arrays in quicksort。所以你希望它在std::sort
中使用。
实际上,我刚调试到std::sort
并且在我的实现上使用插入排序来处理较小的数组(VC ++ 2012)。如果在编译时已知数组的大小为3,那么可以肯定的是,生成的代码将是相当理想的。因此,除非有非常有理由进行优化,否则我会坚持使用std::sort
。
答案 2 :(得分:1)
如果我没有使用std::sort
,我会使用:
template <typename T>
void sort3(T (&a)[3])
{
if (a[0] < a[1]) {
if (a[1] < a[2]) {
return;
} else if (a[0] < a[2]) {
std::swap(a[1], a[2]);
} else {
T tmp = std::move(a[0]);
a[0] = std::move(a[2]);
a[2] = std::move(a[1]);
a[1] = std::move(tmp);
}
} else {
if (a[0] < a[2]) {
std::swap(a[0], a[1]);
} else if (a[2] < a[1]) {
std::swap(a[0], a[2]);
} else {
T tmp = std::move(a[0]);
a[0] = std::move(a[1]);
a[1] = std::move(a[2]);
a[2] = std::move(tmp);
}
}
}
答案 3 :(得分:1)
来自@Jarod42 的sort3 是一种比“通用”算法(来自Jim Mischel)更好的算法(这是网络算法),因为它可以在a[0] < a[1] && a[1 时保存一次比较]
实际上,Jim Mischel 的算法就是冒泡排序算法。
答案 4 :(得分:0)
if (Value1 < Value2)
{
if (Value1 < Value3)
{
if (Value2 < Value3)
{
First = Value1;
Second = Value2;
Third = Value3;
}
else
{
First = Value1;
Second = Value3;
Third = Value2;
}
}
else // Value3 < Value1
{
First = Value3;
Second = Value1;
Third = Value2;
}
}
else // Value2 < Value1
{
if (Value2 < Value3)
{
if (Value1 < Value3)
{
First = Value2;
Second = Value1;
Third = Value3;
}
else
{
First = Value2;
Second = Value3;
Third = Value1;
}
}
else //Value3 < Value2
{
First = Value3;
Second = Value2;
Third = Value1;
}
}