有没有办法迭代订单?

时间:2017-05-11 03:41:58

标签: c syntax logic

如何迭代执行顺序?

我正在开发一个软件,它有几个步骤来计算一些数据,我在考虑可能会以务实的方式改变这些步骤的顺序,这样我就可以检查一些数据的最佳顺序。

让我举例说明:我已经说过3步(实际上更多):

@EJB

我想要一个允许我走路的装置,思考这些步骤的每个排列,然后检查结果。这样的事情:

stepA(data);
stepB(data);
stepC(data);

然后someMagic在i == 0上执行A,B然后执行C. A,C然后B = i == 1。 B,A然后C on i == 2,依此类推。

3 个答案:

答案 0 :(得分:1)

您可以使用函数指针,可能如下所示:

typedef void (*func)(void *data);

int someMagic(void *data, func *func_list, int i) {
    switch (i) {
    case 0:
        func_list[0](data);
        func_list[1](data);
        func_list[2](data);
        break;
    case 1:
        func_list[0](data);
        func_list[2](data);
        func_list[1](data);
        break;
    case 2:
        func_list[1](data);
        func_list[0](data);
        func_list[2](data);
        break;
    default: return 0;
    }
    return 1;
}

func steps[3] = {
    stepA,
    stepB,
    stepC
}

while (someMagic(&data, steps, i++)) {
    ....
}

答案 1 :(得分:1)

关键是要找到一种迭代permutations整数区间的[0, n[集的方法。

排列(在数学意义上)可以被视为[0, n[自身的双射,可以通过这种排列的图像来表示,应用于[0, n[

例如,考虑[0, 3[

的排列
  0 -> 1
  1 -> 2
  2 -> 0

它可以被视为元组(1, 2, 0),它在C中自然地转换为整数数组permutation = (int []){1, 2, 0};

假设您有一组函数指针steps,那么对于每个排列,您都需要为steps[permutation[i]]i的每个值调用[0, n[

以下代码实现了此算法:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static void stepA(int data) { printf("%d: %s\n", data, __func__); }
static void stepB(int data) { printf("%d: %s\n", data, __func__); }
static void stepC(int data) { printf("%d: %s\n", data, __func__); }
static void (* const steps[])(int) = {stepA, stepB, stepC,};
static int fact(int n) { return n == 0 ? 1 : fact(n - 1) * n; }

static int compare_int(const void *pa, const void *pb)
{
    return *(const int *)pa - *(const int *)pb;
}

static void get_next_permutation(int tab[], size_t n)
{
    int tmp;
    unsigned i;
    unsigned j;
    unsigned k;

    /* to find the next permutation in the lexicographic order
     *   source: question 4 (in french, sorry ^^) of
     *   https://liris.cnrs.fr/~aparreau/Teaching/INF233/TP2-permutation.pdf
.    */
    /* 1. find the biggest index i for which tab[i] < tab[i+1] */
    for (k = 0; k < n - 1; k++)
        if (tab[k] < tab[k + 1])
            i = k;

    /* 2. Find the index j of the smallest element, bigger than tab[i],
     *   located after i */
    j = i + 1;
    for (k = i + 1; k < n; k++)
        if (tab[k] > tab[i] && tab[k] < tab[j])
            j = k;

    /* 3. Swap the elements of index i and j */
    tmp = tab[i];
    tab[i] = tab[j];
    tab[j] = tmp;

    /* 4. Sort the array in ascending order, after index i */
    qsort(tab + i + 1, n - (i + 1), sizeof(*tab), compare_int);
}

int main(void)
{
    int n = sizeof(steps) / sizeof(*steps);
    int j;
    int i;
    int permutation[n];
    int f = fact(n);

    /* first permutation is identity */
    for (i = 0; i < n; i++)
        permutation[i] = i;

    for (j = 0; j < f; j++) {
        for (i = 0; i < n; i++)
            steps[permutation[i]](i);
        if (j != f - 1)
            get_next_permutation(permutation, n);
    }

    return EXIT_SUCCESS;
}

main中的外部循环,由j索引,迭代所有n!个排列,而由i索引的内部循环遍历n。 1}}步骤。

get_next_permutation修改了permutation数组,以获得字典顺序中的下一个排列。

请注意,当输入中的排列是最后一个(n - 1, ..., 1, 0)时,不起作用,因此if (j != f - 1)测试。 可以增强它来检测这种情况(我没有设置)并将第一个排列(0, 1, ..., n - 1)放入permutation数组。

可以使用以下代码编译代码:

    gcc main.c -o main -Wall -Wextra -Werror -O0 -g3

我强烈建议使用valgrind作为检测逐个错误的方法。

编辑:我刚刚意识到我没有准确回答OP的问题。 someMagic()函数允许直接访问第i个排列,而我的算法只允许计算字典顺序中的后继。但如果目标是迭代所有排列,它将正常工作。否则,像this one这样的答案可能符合要求。

答案 2 :(得分:0)

我已经找到了一个足够简单的解决方案:

void stepA(STRUCT_NAME *data);
void stepB(STRUCT_NAME *data);
void stepC(STRUCT_NAME *data);

typedef void (*check)(STRUCT_NAME *data);

void swap(check *x, check *y) {    
    check temp;

    temp = *x;
    *x = *y;
    *y = temp;    
}

void permute(check *a, int l, int r,STRUCT_NAME *data) {    
    int i, j = 0, score;
    HAND_T *copy, *copy2, *best_order = NULL;

    if (l == r) {
        j = 0;
        while (j <= r) a[j++](data);
    } else {
        for (i = l; i <= r; i++) {
            swap((a + l), (a + i));
            permute(a, l + 1, r, data);
            swap((a + l), (a + i));
        }
    }    
} 

check checks[3] = {
    stepA,
    stepB,
    stepC,
};

int main(void){
    ...
    permute(checks,0,2,data)
}
相关问题