TL:DR; 您的代码已经正确并且“干净”。
我看到很多人都在四处寻找答案,但是每个人都在树林中迷失了森林。让我们做完整的计算机科学和数学分析以完全理解这个问题。
首先,我们注意到我们有3个变量,每个变量具有3个状态:<,=或>。排列总数为3 ^ 3 = 27个状态,我将为每个状态分配一个唯一的数字,表示为P#。这个P#数字是阶乘数系统。
列举所有的排列:
a ? b | a ? c | b ? c |P#| State
------+-------+-------+--+------------
a < b | a < c | b < c | 0| C
a = b | a < c | b < c | 1| C
a > b | a < c | b < c | 2| C
a < b | a = c | b < c | 3| impossible a<b b<a
a = b | a = c | b < c | 4| impossible a<a
a > b | a = c | b < c | 5| A=C > B
a < b | a > c | b < c | 6| impossible a<c a>c
a = b | a > c | b < c | 7| impossible a<c a>c
a > b | a > c | b < c | 8| A
a < b | a < c | b = c | 9| B=C > A
a = b | a < c | b = c |10| impossible a<a
a > b | a < c | b = c |11| impossible a<c a>c
a < b | a = c | b = c |12| impossible a<a
a = b | a = c | b = c |13| A=B=C
a > b | a = c | b = c |14| impossible a>a
a < b | a > c | b = c |15| impossible a<c a>c
a = b | a > c | b = c |16| impossible a>a
a > b | a > c | b = c |17| A
a < b | a < c | b > c |18| B
a = b | a < c | b > c |19| impossible b<c b>c
a > b | a < c | b > c |20| impossible a<c a>c
a < b | a = c | b > c |21| B
a = b | a = c | b > c |22| impossible a>a
a > b | a = c | b > c |23| impossible c>b b>c
a < b | a > c | b > c |24| B
a = b | a > c | b > c |25| A=B > C
a > b | a > c | b > c |26| A
通过检查,我们看到:
- 3个州,其中A是最大值,
- 3个州,其中B是最大值,
- 3个州,其中C是最大值,并且
- 4个州,其中A = B或B = C。
让我们编写一个程序(请参阅脚注)以使用A,B和C的值枚举所有这些排列。通过P#进行稳定排序:
a ?? b | a ?? c | b ?? c |P#| State
1 < 2 | 1 < 3 | 2 < 3 | 0| C
1 == 1 | 1 < 2 | 1 < 2 | 1| C
1 == 1 | 1 < 3 | 1 < 3 | 1| C
2 == 2 | 2 < 3 | 2 < 3 | 1| C
2 > 1 | 2 < 3 | 1 < 3 | 2| C
2 > 1 | 2 == 2 | 1 < 2 | 5| ??
3 > 1 | 3 == 3 | 1 < 3 | 5| ??
3 > 2 | 3 == 3 | 2 < 3 | 5| ??
3 > 1 | 3 > 2 | 1 < 2 | 8| A
1 < 2 | 1 < 2 | 2 == 2 | 9| ??
1 < 3 | 1 < 3 | 3 == 3 | 9| ??
2 < 3 | 2 < 3 | 3 == 3 | 9| ??
1 == 1 | 1 == 1 | 1 == 1 |13| ??
2 == 2 | 2 == 2 | 2 == 2 |13| ??
3 == 3 | 3 == 3 | 3 == 3 |13| ??
2 > 1 | 2 > 1 | 1 == 1 |17| A
3 > 1 | 3 > 1 | 1 == 1 |17| A
3 > 2 | 3 > 2 | 2 == 2 |17| A
1 < 3 | 1 < 2 | 3 > 2 |18| B
1 < 2 | 1 == 1 | 2 > 1 |21| B
1 < 3 | 1 == 1 | 3 > 1 |21| B
2 < 3 | 2 == 2 | 3 > 2 |21| B
2 < 3 | 2 > 1 | 3 > 1 |24| B
2 == 2 | 2 > 1 | 2 > 1 |25| ??
3 == 3 | 3 > 1 | 3 > 1 |25| ??
3 == 3 | 3 > 2 | 3 > 2 |25| ??
3 > 2 | 3 > 1 | 2 > 1 |26| A
如果您想知道我如何知道哪些P#状态是不可能的,那么现在您知道了。:-)
确定顺序的最小比较数为:
Log2(27)= Log(27)/ Log(2)=〜4.75 = 5个比较
即coredump给出了正确的5个最小比较数。我将他的代码格式化为:
status_t index_of_max_3(a,b,c)
{
if (a > b) {
if (a == c) return DONT_KNOW; // max a or c
if (a > c) return MOSTLY_A ;
else return MOSTLY_C ;
} else {
if (a == b) return DONT_KNOW; // max a or b
if (b > c) return MOSTLY_B ;
else return MOSTLY_C ;
}
}
对于您的问题,我们不在乎是否进行相等性测试,因此我们可以省略2个测试。
如果得到错误的答案,代码有多干净/不好都没关系,因此这是您正确处理所有情况的好兆头!
接下来,为简单起见,人们一直试图“改善”答案,他们认为改善意味着“优化”比较次数,但严格来说,这并不是您要问的。您在询问“我觉得可能会有更好”的每个人面前感到困惑,但没有定义“更好”的含义。比较少?更少的代码?最佳比较?
现在,由于您询问的是代码的可读性(给定的正确性),因此我仅对代码进行一次更改以提高可读性:将第一个测试与其他测试对齐。
if (a > b && a > c)
status = MOSTLY_A;
else if (b > a && b > c)
status = MOSTLY_B;
else if (c > a && c > b)
status = MOSTLY_C;
else
status = DONT_KNOW; // a=b or b=c, we don't care
我个人将以以下方式编写它,但这对于您的编码标准而言可能太过传统了:
if (a > b && a > c) status = MOSTLY_A ;
else if (b > a && b > c) status = MOSTLY_B ;
else if (c > a && c > b) status = MOSTLY_C ;
else /* a==b || b ==c*/status = DONT_KNOW; // a=b or b=c, we don't care
脚注:这是生成排列的C ++代码:
#include <stdio.h>
char txt[] = "< == > ";
enum cmp { LESS, EQUAL, GREATER };
int val[3] = { 1, 2, 3 };
enum state { DONT_KNOW, MOSTLY_A, MOSTLY_B, MOSTLY_C };
char descr[]= "??A B C ";
cmp Compare( int x, int y ) {
if( x < y ) return LESS;
if( x > y ) return GREATER;
/* x==y */ return EQUAL;
}
int main() {
int i, j, k;
int a, b, c;
printf( "a ?? b | a ?? c | b ?? c |P#| State\n" );
for( i = 0; i < 3; i++ ) {
a = val[ i ];
for( j = 0; j < 3; j++ ) {
b = val[ j ];
for( k = 0; k < 3; k++ ) {
c = val[ k ];
int cmpAB = Compare( a, b );
int cmpAC = Compare( a, c );
int cmpBC = Compare( b, c );
int n = (cmpBC * 9) + (cmpAC * 3) + cmpAB; // Reconstruct unique P#
printf( "%d %c%c %d | %d %c%c %d | %d %c%c %d |%2d| "
, a, txt[cmpAB*2+0], txt[cmpAB*2+1], b
, a, txt[cmpAC*2+0], txt[cmpAC*2+1], c
, b, txt[cmpBC*2+0], txt[cmpBC*2+1], c
, n
);
int status;
if (a > b && a > c) status = MOSTLY_A;
else if (b > a && b > c) status = MOSTLY_B;
else if (c > a && c > b) status = MOSTLY_C;
else /* a ==b || b== c*/status = DONT_KNOW; // a=b, or b=c
printf( "%c%c\n", descr[status*2+0], descr[status*2+1] );
}
}
}
return 0;
}
编辑:根据反馈,将TL:DR移到顶部,删除了未排序的表,明确了27,清理了代码,描述了不可能的状态。