C 有没有一种迭代顺序的方法?
如何迭代执行顺序 我正在开发一个软件,它有几个步骤来计算一些数据,我在五月份考虑实用地改变这些步骤的顺序,这样我就可以检查一些数据的最佳顺序 让我举例说明:我有3个步骤(实际上更多): 我想要一个装置,可以让我思考这些步骤的每一个排列,然后检查结果。诸如此类:C 有没有一种迭代顺序的方法?,c,syntax,logic,C,Syntax,Logic,如何迭代执行顺序 我正在开发一个软件,它有几个步骤来计算一些数据,我在五月份考虑实用地改变这些步骤的顺序,这样我就可以检查一些数据的最佳顺序 让我举例说明:我有3个步骤(实际上更多): 我想要一个装置,可以让我思考这些步骤的每一个排列,然后检查结果。诸如此类: data = originalData; i=0; while (someMagic(&data,[stepA,stepB,stepC],i++)){ checkResults(data); data = origin
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语句中写出所有置换。这是一个关于如何编写置换函数的问题吗?这是一个关于如何编写置换函数的问题吗?我喜欢您的答案,但我已经给出了答案今天早上还有更好的,更简单的,我会的