用重复数字打印所有排列的算法

时间:2014-11-03 12:33:15

标签: algorithm

我已成功设计算法,以重复数字打印所有排列。但我设计的算法有一个缺陷。仅当字符串的字符是唯一的时才有效。

在字符串的字符可能不唯一的情况下,有人可以帮助我扩展算法吗? 到目前为止我的代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iostream>

using namespace std;

void _perm(char *arr, char*result, int index)
{
    static int count = 1;
    if (index == strlen(arr))
    {
        cout << count++ << ". " << result << endl;
        return;
    }
    for (int i = 0; i < strlen(arr); i++)
    {
        result[index] = arr[i];
        _perm(arr, result, index + 1);
    }
}

int compare(const void *a, const void *b)
{
    return (*(char*)a - *(char*)b);
}



void perm(char *arr)
{
    int n = strlen(arr);
    if (n == 0)
        return;
    qsort(arr, n, sizeof(char), compare);
    char *data = new char[n];
    _perm(arr, data, 0);
    free(data);
    return;
}



int main()
{
    char arr[] = "BACD";
    perm(arr);
    return 0;
}

我按字典顺序打印输出字符串。

我指的是本页的例子。

http://www.vitutor.com/statistics/combinatorics/permutations_repetition.html

感谢。

1 个答案:

答案 0 :(得分:1)

您的代码不会打印排列,但会重复四次从字符串池中提取。它将产生4^4 == 256个组合,其中一个是“AAAA”。

链接到的代码Karnuakar将为您提供字符串的排列,但不区分某些字母的多次出现。您需要一些方法来防止在每个递归步骤中使用相同的字母进行递归。在C ++中,可以使用set来完成。

下面的示例代码使用典型的C字符串,但使用终止'\0'来检测结束。不需要<cstring>的C字符串函数。除非原始字符串已排序,否则不会对输出进行排序。

#include <iostream>
#include <algorithm>
#include <set>

using namespace std;

void perm(char *str, int index = 0)
{
    std::set<char> used;

    char *p = str + index;
    char *q = p;

    if (*p == '\0') {
        std::cout << str << std::endl;
        return;
    }

    while (*q) {
        if (used.find(*q) == used.end()) {
            std::swap(*p, *q);
            perm(str, index + 1);
            std::swap(*p, *q);

            used.insert(*q);
        }
        q++;
    }
}

int main()
{
    char arr[] = "AAABB";
    perm(arr);

    return 0;
}

这将为“ABCDE”生成5! == 120个排列,但“AAABB”只会生成5! / (2! 3!) == 10个唯一排列。它还将从链接的练习中创建1260个排列。