快速排序3个值

时间:2014-04-06 16:54:53

标签: c++ arrays algorithm sorting

我有一个包含三个浮点值的数组,我想按升序对它们进行排序(尽管可能很容易逆转任何排序算法的顺序)。调用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

5 个答案:

答案 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;
        }
    }