如何置换2d char数组

时间:2016-03-31 05:27:48

标签: c

所以我在这里遇到这个问题,我需要使用2d char数组的所有可能组合来查找某个值。

void permutate(int i, int r, int m, int factor, int count, char** danceRoutines);

int main(void)
{
    int routines, i, j, loop, factor, min, count = 0;

    printf("Please enter the number of routines (min 2, max 10): \n");
    scanf("%d", &routines);
    factor = factorial(routines);

    //Check for routine < 2 and routine > 10
    if(routines < 2 || routines > 10)
    {
        printf("Please, between 2 and 10 \n");
        return;
    }

    //Store the dancers they enter into a 2d array of size routines *  MAX
    char **danceRoutines = (char**)malloc(sizeof(char*) * routines);
    for(i = 0; i < routines; i++)
    {
        char *s = (char*)malloc(sizeof(char));
        scanf("%s", s);
        danceRoutines[i] = s;
    }

    min = quickChanges(danceRoutines, routines, 0);
    printf("This is min: %d", min);
    permutate(0, routines, min, factor, count, danceRoutines);

    for(loop = 0; loop < routines; loop++)
    {
        free(danceRoutines[loop]);
    }

    free(danceRoutines);
    return 0;
}

void permutate(int i, int r, int m, int factor, int count, char** danceRoutines)
{
    int k, l, test, last;
    if(last == 0)
    {
        printf("%d", m);
    }

    for(k = 0; k < r; k++)
    {
        int length = strlen(danceRoutines[k]);
        char *line = (char*)malloc(sizeof(char) * length);
        strcpy(line, danceRoutines[k]);
        strcpy()
        for(l = 1; l < factor / r; l++)
        {

        }
    }
}

因子基本上是读入函数的整数r的阶乘。是否有更简单的方法为2d字符数组创建排列?

1 个答案:

答案 0 :(得分:1)

使用常规排列代码。你可以在SO上找到数以万计的例子,尽管大多数都是在字符串上写字。

在您的设置中,字符串在堆上分配,并由指向它们的指针表示。这很好,因为现在你可以通过交换指针来交换字符串:

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



void permute(const char **str, size_t n, size_t i)
{
    size_t j;

    if (i == n) {        
        // permutation found: print the strings (or do other stuff)
        for (j = 0; j < n; j++) {
            if (j) printf(" ");
            printf("%s", str[j]);
        }
        puts("");
    } else {
        // recurse deeper with each of the remaining strings as next string

        for (j = i; j < n; j++) {
            const char *swap;

            swap = str[i]; str[i] = str[j]; str[j] = swap;
            permute(str, n, i + 1);
            swap = str[i]; str[i] = str[j]; str[j] = swap;
        }
    }
}

int main(void)
{
    const char *str[] = {
        "red", "green", "blue", "white"
    };

    permute(str, 4, 0);

    return 0;
}

为了简洁起见,我在此处使用了字符串文字,但如果您在示例中使用strdupmallocstrcpy,则代码也能正常运行。

如果您使用具有固定字符串大小的真实二维数组,如char a[10][20],则必须复制字符串的内容,这是昂贵的。在这种情况下,最好创建一个存储指向这些字符串的指针的第二个数组,并按上述步骤继续。

Ceterum censeo :我仍然不相信您需要创建所有排列。)

编辑:如果您想找到所有相邻字符串之间的公共字母最少的排列,请不要首先交换字符串。代替:

  • 创建一个矩阵,其中w[i][j]哈希字符串ij之间的常用字母数。
  • 然后从{0, 1, 2, ..., n}开始对整数ixed数组进行排列。
  • 随时累积惩罚金额。找到排列后,检查它是否是最小的。
  • 当您知道当前总和不能最小时,您可以缩短递归时间。

所以:

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

#define MAX 10

int weight[MAX][MAX];
int best[MAX];
int min;


void permute(int *perm, size_t n, size_t i, int sum)
{
    size_t j;

    if (sum >= min) return;

    if (i == n) {
        if (sum < min) {
            min = sum;
            memcpy(best, perm, n * sizeof(*perm));
        }
    } else {
        for (j = i; j < n; j++) {
            int swap;
            int w = 0;

            if (i) w = weight[perm[i - 1]][perm[j]];

            swap = perm[i]; perm[i] = perm[j]; perm[j] = swap;
            permute(perm, n, i + 1, sum + w);
            swap = perm[i]; perm[i] = perm[j]; perm[j] = swap;
        }
    }
}

int common(const char *s, const char *t)
{
    int res = 0;

    while (*s && *t) {
        if (*s == *t) {
            res++; s++; t++;
        } else {
            if (*s < *t) s++; else t++;
        }
    }

    return res;
}

void best_perm(const char **str, size_t n)
{
    int perm[n];
    size_t i, j;

    for (i = 0; i < n; i++) perm[i] = i;

    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            weight[i][j] = weight[j][i] = common(str[i], str[j]);
        }
    }

    min = INT_MAX;

    permute(perm, n, 0, 0);

    for (i = 0; i < n; i++) {
        if (i) printf(" %d ", weight[best[i - 1]][best[i]]);
        printf("%s", str[best[i]]);
    }
    printf("\nOverall penalty: %d\n", min);    
}

int main(void)
{
    const char *str[] = {
        "acdeg", "acgh", "dg", "aeh", "cegh", 
        "abcfgh", "abc", "abc", "fgh", "abcdefgh"
    };

    best_perm(str, 10);

    return 0;
}

这个解决方案仍然基本上尝试了所有的排列,可能不是最优的。如果您将权重矩阵视为图形中的距离矩阵,您可以尝试使用任何已知的图形查找算法来解决问题。这看起来像是一个引人注目的推销员问题,其中的路径并没有完全循环。