最低编号比较找到3个数字的中位数

时间:2013-06-17 23:53:35

标签: median

我正在实施quicksort,我希望将枢轴设置为中位数或三位数。这三个数字是第一个元素,中间元素和最后一个元素。

我是否可以找到中位数而不是。比较?

median(int a[], int p, int r)
{
    int m = (p+r)/2;
    if(a[p] < a[m])
    {
        if(a[p] >= a[r])
            return a[p];
        else if(a[m] < a[r])
            return a[m];
    }
    else
    {
        if(a[p] < a[r])
            return a[p];
        else if(a[m] >= a[r])
            return a[m];
    }
    return a[r];
}

10 个答案:

答案 0 :(得分:10)

如果只关注比较,那么应该使用它。

int getMedian(int a, int b , int c) {
    int x = a-b;
    int y = b-c;
    int z = a-c;
    if(x*y > 0) return b;
    if(x*z > 0) return c;
    return a;
}

答案 1 :(得分:4)

你不能一个人做,而你只使用两个或三个,所以我说你已经有了最少的比较次数。

答案 2 :(得分:4)

不仅可以计算中位数,还可以将它们放在适当的位置。然后你可以随时进行3次比较,并且你已经有了更接近的位置。

T median(T a[], int low, int high)
{
    int middle = ( low + high ) / 2;
    if( a[ middle ].compareTo( a[ low ] ) < 0 )
        swap( a, low, middle );
    if( a[ high ].compareTo( a[ low ] ) < 0 )
        swap( a, low, high );
    if( a[ high ].compareTo( a[ middle ] ) < 0 )
        swap( a, middle, high );

    return a[middle];
}

答案 3 :(得分:4)

int32_t FindMedian(const int n1, const int n2, const int n3) {
    auto _min = min(n1, min(n2, n3));
    auto _max = max(n1, max(n2, n3));
    return (n1 + n2 + n3) - _min - _max;
}

答案 4 :(得分:2)

如果你不害怕使用编译器内在函数让你的手变得有点脏,你可以用0分支来完成它。

之前讨论了同样的问题:
Fastest way of finding the middle value of a triple?

尽管如此,我必须在快速排序的天真实现的背景下添加,有很多元素,在找到中位数时减少分支的数量并不是那么重要,因为分支预测器将会阻塞任何一种方式开始在枢轴周围抛掷元素。更复杂的实现(不分支在分区操作上,避免WAW危险)将从中受益匪浅。

答案 5 :(得分:1)

实际上有一种聪明的方法可以通过仔细分析6种可能的排列(低,中,高)来将中值元素与三种元素隔离开来。在python:

def med(a, start, mid, last):
    # put the median of a[start], a[mid], a[last] in the a[start] position
    SM = a[start] < a[mid]
    SL = a[start] < a[last]
    if SM != SL:
        return
    ML = a[mid] < a[last]
    m = mid if SM == ML else last
    a[start], a[m] = a[m], a[start]

有两次比较,否则你有3次(平均2.5)。并且您只需在需要时交换一次中值元素(2/3的时间)。

完整的python quicksort使用它:

https://github.com/mckoss/labs/blob/master/qs.py

答案 6 :(得分:1)

从总和中删除最大值和最小值

int med3(int a, int b, int c)
{
    int tot_v = a + b + c ;
    int max_v = max(a, max(b, c));
    int min_v = min(a, min(b, c));
    return tot_v - max_v - min_v
}

答案 7 :(得分:0)

你可以写出所有的排列:

    1 0 2
    1 2 0
    0 1 2
    2 1 0
    0 2 1
    2 0 1

然后我们想要找到1的位置。我们可以通过两次比较来做到这一点,如果我们的第一次比较可以分割出一组相等的位置,例如前两行。

问题似乎是前两行在我们提供的任何比较中都有所不同:a<ba<cb<c。因此,我们必须完全识别排列,在最坏的情况下需要进行3次比较。

答案 8 :(得分:0)

我知道这是一个旧线程,但我必须在具有非常少的RAM并且没有h / w乘法单元(:)的微控制器上解决这个问题。最后我发现以下效果很好:

static char medianIndex[] = { 1, 1, 2, 0, 0, 2, 1, 1 };

signed short getMedian(const signed short num[])
{
    return num[medianIndex[(num[0] > num[1]) << 2 | (num[1] > num[2]) << 1 | (num[0] > num[2])]];
}

答案 9 :(得分:0)

使用按位异或运算符,可以找到三个数字的中位数。

def median(a,b,c):
    m = max(a,b,c)
    n = min(a,b,c)
    ans = m^n^a^b^c
    return ans