如何迭代执行顺序?
我正在开发一个软件,它有几个步骤来计算一些数据,我在考虑可能会以务实的方式改变这些步骤的顺序,这样我就可以检查一些数据的最佳顺序。
让我举例说明:我已经说过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,依此类推。
答案 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)
}