生成范围内字符串的排列

时间:2014-02-13 16:18:34

标签: c algorithm permutation

我正在寻找一种非常有效的方法来生成字符串(或字母表)的所有可能的排列,其中排列长度由两个变量(i, j)在下方和上方限定。

到目前为止,我已经能够以多种方式生成排列,例如......

void swap(char *x, char *y){
    char w;
    w = *x;
    *x = *y;
    *y = w;
}

void permute(char *str, int start, int n){
    int i;

    if(start == n-1)
        printf("%s\n", str);
    else
        for(i = start; i < n; i++){
            swap(str+i, str+start);
            permute(str, start+1, n);
            swap(str+i, str+start);
        }
}

...但到目前为止我找不到的算法将有效地限制结果字符串的长度。例如,如果字母表被定义为abcdei = 2j = 4 ......这会产生abbac等排列, dcea,但不是aedcba,由于算法不是计算组合,因此也不会产生aab等字符串。

1 个答案:

答案 0 :(得分:1)

如果只是将最小和最大长度传递给函数,并在start介于两者之间时打印字符串呢?

代码:

void permute(char *str, int start, int n, int minLength, int maxLength)
{
    int i;

    if (start >= minLength)
    {
        char temp = str[start]; // store the character, so we don't lose it
        str[start] = 0; // 0x00 - end of string
        printf("%s\n", str);
        str[start] = temp;
    }

    if (start == maxLength)
        return;

    for (i = start; i < n; i++)
    {
        swap(str+i, str+start);
        permute(str, start+1, n, minLength, maxLength);
        swap(str+i, str+start);
    }
}

Live demo


如果数据中有重复项,并且您想要防止重复排列,那么您需要做的就是:

  • 将字母排序为开头,以便任何重复的字符彼此相邻

  • 如果最后一个字符与此字符相同,请勿执行任何操作。这可以通过简单地将以下代码添加到for循环的开头来完成:

    if (i != start && str[i] == str[i-1])
        continue;
    

Live demo