使用if-else对3个值排序的最有效的c程序是什么?

时间:2019-03-26 18:42:18

标签: c algorithm sorting

让我们认为,我需要开发一个程序,该程序读取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;
}

3 个答案:

答案 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.cst19.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变体对v0v1v2进行排序,您将得到:

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}));    

}