让我们认为,我需要开发一个程序,该程序读取3个值,并仅使用if-else结构以升序打印这些值。
请注意,我知道经典的排序算法。但是这里的重点是如何使用简单的条件结构为3个值开发排序算法。
我已经实现了2个版本。我需要确定哪一个是最有效的,为什么。让我们考虑效率与程序所花费的时间成反比。
我认为衡量这一点的一种方法是计算必要的最小和最大比较量。即,评估最佳和最坏的情况。但是两种算法中ifs中的条件数是不同的。
让我们忽略printf花费的时间。
版本1:
#include <stdio.h>
int main()
{
int v1,v2,v3;
printf("Provide 3 values:\n");
scanf("%d%d%d",&v1,&v2,&v3);
if ( v1 <= v2 && v1 <= v3){
if( v2 <= v3 ){
printf("%d, %d, %d\n", v1, v2, v3);
}
else{
printf("%d, %d, %d\n", v1, v3, v2);
}
}
else{
if(v2 <= v1 && v2 <= v3){
if(v1 <= v3){
printf("%d, %d, %d\n", v2, v1, v3);
}
else{
printf("%d, %d, %d\n", v2, v3, v1);
}
}
else{
if(v2 <= v1){
printf("%d, %d, %d\n", v3, v2, v1);
}
else{
printf("%d, %d, %d\n", v3, v1, v2);
}
}
}
return 0;
}
版本2
#include <stdio.h>
int main()
{
int v1,v2,v3;
printf("Provide 3 values:\n");
scanf("%d%d%d",&v1,&v2,&v3);
if ( v1 <= v2){
if( v1 <= v3 ){
if(v2 <= v3){
printf("%d, %d, %d\n", v1, v2, v3);
}
else{
printf("%d, %d, %d\n", v1, v3, v2);
}
}
else{
printf("%d, %d, %d\n", v3, v1, v2);
}
}
else{
if(v2 <= v3){
if(v1 <= v3){
printf("%d, %d, %d\n", v2, v1, v3);
}
else{
printf("%d, %d, %d\n", v2, v3, v1);
}
}
else{
printf("%d, %d, %d\n", v3, v2, v1);
}
}
return 0;
}
是否有其他程序(仅使用if-else)比这两个程序更有效?
@rcgldr您可以显示实现您的想法的代码吗?
版本3
int main()
{
int v1,v2,v3;
printf("Provide 3 values:\n");
scanf("%d%d%d",&v1,&v2,&v3);
if(v1 <= v2){
if(v2 <= v3){
printf("%d, %d, %d\n", v1, v2, v3);
}else if(v1 <= v3 ){
printf("%d, %d, %d\n", v1, v3, v2);
}else{
printf("%d, %d, %d\n", v3, v1, v2);
}
}
else{
if(v1 <= v3){
printf("%d, %d, %d\n", v2, v1, v3);
}else if(v2 <= v3){
printf("%d, %d, %d\n", v2, v3, v1);
}else{
printf("%d, %d, %d\n", v3, v2, v1);
}
}
return 0;
}
答案 0 :(得分:1)
判断效率非常困难,因为它高度依赖于CPU和编译器的优化器。
但是,从理论上讲,对3个元素进行排序需要至少3个比较。 Sequence A036604具有用于更多元素的值。
显示了用于对5个元素进行排序的代码here-您可能会明白为什么这种排序不经常使用。
答案 1 :(得分:0)
这是我与问题SO 4203-5818相关联创建的一些代码(实际上与排序无关)。它用于对3个元素的数组(另一个问题中的三角形的边)进行排序,但不是该问题的答案。
假设您可以/希望对数据进行排序,而不只是按照排序顺序列出数据,则可以使用以下代码中显示的sort_3()
变体之一,以适合您的情况。
它包含测试代码,该代码测试从{0,1,2}中选择的3个值的每个组合。它使用3个比较和最多3个交换对数据进行排序。
/* Sort 3 items - fixed comparisons */
/* Based on code for SO 4203-5818 */
#include <assert.h>
#include <stdio.h>
static inline void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; }
/* Interesting: 4 of 6 permutations work, 2 fail */
#if P_01_02_12 + P_01_12_02 + \
P_02_01_12 + P_02_12_01 + \
P_12_01_02 + P_12_02_01 > 1
#error Too many of the control macros (P_[01][12]_[01][12]_[01][12]) are set
#endif
#if P_01_02_12 + P_01_12_02 + \
P_02_01_12 + P_02_12_01 + \
P_12_01_02 + P_12_02_01 == 0
#define P_02_01_12 1
#endif
#define P_STRING(x) static char const variant[] = #x
#ifdef P_01_02_12
P_STRING(P_01_02_12);
#endif
#ifdef P_01_12_02
P_STRING(P_01_12_02);
#endif
#ifdef P_02_01_12
P_STRING(P_02_01_12);
#endif
#ifdef P_02_12_01
P_STRING(P_02_12_01);
#endif
#ifdef P_12_01_02
P_STRING(P_12_01_02);
#endif
#ifdef P_12_02_01
P_STRING(P_12_02_01);
#endif
#if P_02_01_12
/* Working */
static void sort_3(int *a)
{
if (a[0] > a[2]) swap(&a[0], &a[2]);
if (a[0] > a[1]) swap(&a[0], &a[1]);
if (a[1] > a[2]) swap(&a[1], &a[2]);
}
#endif /* 0 */
#if P_12_01_02
/* Triggers assertion */
static void sort_3(int *a)
{
if (a[1] > a[2]) swap(&a[1], &a[2]);
if (a[0] > a[1]) swap(&a[0], &a[1]);
if (a[0] > a[2]) swap(&a[0], &a[2]);
}
#endif /* 0 */
#if P_01_12_02
/* Triggers assertion */
static void sort_3(int *a)
{
if (a[0] > a[1]) swap(&a[0], &a[1]);
if (a[1] > a[2]) swap(&a[1], &a[2]);
if (a[0] > a[2]) swap(&a[0], &a[2]);
}
#endif /* 0 */
#if P_12_02_01
/* Working */
static void sort_3(int *a)
{
if (a[1] > a[2]) swap(&a[1], &a[2]);
if (a[0] > a[2]) swap(&a[0], &a[2]);
if (a[0] > a[1]) swap(&a[0], &a[1]);
}
#endif /* 0 */
#if P_02_12_01
/* Working */
static void sort_3(int *a)
{
if (a[0] > a[2]) swap(&a[0], &a[2]);
if (a[1] > a[2]) swap(&a[1], &a[2]);
if (a[0] > a[1]) swap(&a[0], &a[1]);
}
#endif /* 0 */
#if P_01_02_12
/* Working */
static void sort_3(int *a)
{
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]);
}
#endif /* 0 */
static void print_3(int *a)
{
const char *pad = "";
for (int i = 0; i < 3; i++)
{
printf("%s%d", pad, a[i]);
pad = " ";
}
}
static void check_3(int *a)
{
assert(a[0] <= a[1]);
assert(a[1] <= a[2]);
}
int main(void)
{
printf("Variant: %s\n", variant);
fflush(stdout);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
int a[3] = { i, j, k };
print_3(a);
fputs(" : ", stdout);
sort_3(a);
print_3(a);
putchar('\n');
check_3(a);
}
}
}
return 0;
}
您可以在我的GitHub上的SOQ(堆栈溢出问题)存储库中以文件st13.c
(以及该思想的变体的st17.c
和st19.c
)找到此代码。 src/so-4203-5818子目录。请注意,st19
(和测试脚本test.st19.sh
)表明存在6种可能的工作类别-01:02:12、01:12:01、02:01:12、02:12:01 ,12:01:12,12:02:01-在27种(3 3 )可能的组合中。 (st13
中没有演示01:12:01和12:01:12工作变体,而st19
可以演示。)
如果必须使用不相交的名称对3个变量进行排序,则可以使任何有效的数组排序函数适应内联工作。例如,使用P_01_02_12变体对v0
,v1
,v2
进行排序,您将得到:
if (v0 > v1) swap(&v0, &v1);
if (v0 > v2) swap(&v0, &v2);
if (v1 > v2) swap(&v1, &v2);
答案 2 :(得分:-1)
原谅这不是if-then-else,但这里有3个测试和6个作业 (在副本中传递三个,在复合文字构造中传递三个。
#include <assert.h>
struct triplet
{
int i1, i2, i3; // least, middle, greatest
};
// convert triplet order to lowest to highest
struct triplet order3(struct triplet in)
{
return
( in.i1 > in.i2 ?
(in.i3 > in.i1 ?
(struct triplet){.i3=in.i3, .i2=in.i1, .i1=in.i2}
:(in.i3 > in.i2 ?
(struct triplet){.i3=in.i1, .i2=in.i3, .i1=in.i2}
: (struct triplet){.i3=in.i1, .i2=in.i2, .i1=in.i3}))
: (in.i3 > in.i2 ?
(struct triplet){.i3=in.i3, .i2=in.i2, .i1=in.i1}
: (in.i3 > in.i1 ?
(struct triplet){.i3=in.i2, .i2=in.i3, .i1=in.i1}
: (struct triplet){.i3=in.i2, .i2=in.i1, .i1=in.i3}))
);
}
void testIt(struct triplet in)
{
assert(in.i3 > in.i2);
assert(in.i2 > in.i1);
}
void main(void)
{
testIt(order3((struct triplet){10,20,30}));
testIt(order3((struct triplet){20,10,30}));
testIt(order3((struct triplet){30,10,20}));
testIt(order3((struct triplet){10,30,20}));
testIt(order3((struct triplet){20,30,10}));
testIt(order3((struct triplet){30,20,10}));
}