C 有没有一种迭代顺序的方法?

C 有没有一种迭代顺序的方法?,c,syntax,logic,C,Syntax,Logic,如何迭代执行顺序 我正在开发一个软件,它有几个步骤来计算一些数据,我在五月份考虑实用地改变这些步骤的顺序,这样我就可以检查一些数据的最佳顺序 让我举例说明:我有3个步骤(实际上更多): 我想要一个装置,可以让我思考这些步骤的每一个排列,然后检查结果。诸如此类: data = originalData; i=0; while (someMagic(&data,[stepA,stepB,stepC],i++)){ checkResults(data); data = origin

如何迭代执行顺序

我正在开发一个软件,它有几个步骤来计算一些数据,我在五月份考虑实用地改变这些步骤的顺序,这样我就可以检查一些数据的最佳顺序

让我举例说明:我有3个步骤(实际上更多):

我想要一个装置,可以让我思考这些步骤的每一个排列,然后检查结果。诸如此类:

data = originalData; i=0;
while (someMagic(&data,[stepA,stepB,stepC],i++)){
   checkResults(data);
   data = originalData;
}

然后在i==0上执行A、B和C。A、 然后是i==1上的B。B、 A然后是i==2上的C,依此类推。

您可以使用函数指针,可能类似于以下内容:

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++)) {
    ....
}

您可以使用函数指针,例如:

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++)) {
    ....
}

关键是找到一种方法来迭代
[0,n[
整数区间的
置换集

置换(在数学意义上)可以被看作是
[0,n[
自身的双射,并且可以通过应用于
[0,n[
的该置换的图像来表示

例如,考虑<代码>的排列〔0, 3〕/代码>:

  0 -> 1
  1 -> 2
  2 -> 0
它可以看作是元组
(1,2,0)
,在C中,它自然地转换为整数数组
置换=(int[]){1,2,0};

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

以下代码实现此算法:

#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;
}
我强烈建议使用
valgrind
作为一种逐个检测错误的方法


编辑:我刚刚意识到我没有准确地回答OP的问题。
someMagic()
函数将允许直接访问第i个排列,而我的算法只允许按字典顺序计算后续排列。但是如果目标是迭代所有排列,它将很好地工作。否则,可能一个类似的答案应该符合要求。

关键是找到一种方法来迭代这组排列<
[0,n[
整数区间的code>置换

置换(在数学意义上)可以被看作是
[0,n[
自身的双射,并且可以通过应用于
[0,n[
的该置换的图像来表示

例如,考虑<代码>的排列〔0, 3〕/代码>:

  0 -> 1
  1 -> 2
  2 -> 0
它可以看作是元组
(1,2,0)
,在C中,它自然地转换为整数数组
置换=(int[]){1,2,0};

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

以下代码实现此算法:

#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;
}
我强烈建议使用
valgrind
作为一种逐个检测错误的方法


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

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

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)
}
void stepA(结构名称*数据);
无效步骤B(结构名称*数据);
void stepC(结构名称*数据);
typedef void(*检查)(结构名称*数据);
无效交换(勾选*x,勾选*y){
检查温度;
温度=*x;
*x=*y;
*y=温度;
}
void permute(检查*a、int l、int r、STRUCT_NAME*数据){
int i,j=0,得分;
手工复制,*copy2,*best\u order=NULL;
如果(l==r){
j=0;

(j我找到了一个非常简单的解决方案:

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)
}
void stepA(结构名称*数据);
无效步骤B(结构名称*数据);
void stepC(结构名称*数据);
typedef void(*检查)(结构名称*数据);
无效交换(勾选*x,勾选*y){
检查温度;
温度=*x;
*x=*y;
*y=温度;
}
void permute(检查*a、int l、int r、STRUCT_NAME*数据){
int i,j=0,得分;
手工复制,*copy2,*best\u order=NULL;
如果(l==r){
j=0;

(j)这将按顺序执行它们,我需要一些排列/交换和几个执行。如果可以交换它们,只需在函数列表中设置实际函数。例如,步骤[1]=stepC;步骤[2]=stepB;将交换B和C。@emiliopedrollo嘿,我已经编辑了我的帖子,现在可以了吗?它适用于只有3个函数的情况,但不能很好地扩展。我的实际代码有7个函数。为什么会这样?为什么不排列
步骤
数组,然后简单地执行(排列)中的步骤顺序?因此,您有一个简单的
循环来执行步骤,而不是随着步骤数的增加在一个快速增长的switch语句中写出所有排列。这将按顺序执行它们,我需要一些排列/交换和几个执行。如果您可以交换它们,只需在函数列表中设置实际的函数即可。例如,步骤[1]=stepC;步骤[2]=stepB;将交换B和C。@emiliopedrollo嘿,我编辑了我的帖子,现在可以吗?它将适用于只有3个函数的情况,但不能很好地扩展。我的实际代码有7个函数。为什么会这样?为什么不排列
步骤
数组,然后简单地执行(排列)中的步骤顺序?因此,您有一个简单的
循环来执行步骤,而不是随着步骤数的增加在一个快速增长的switch语句中写出所有置换。这是一个关于如何编写置换函数的问题吗?这是一个关于如何编写置换函数的问题吗?我喜欢您的答案,但我已经给出了答案今天早上还有更好的,更简单的,我会的