我正在实施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];
}
答案 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使用它:
答案 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<b
,a<c
,b<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