我已成功设计算法,以重复数字打印所有排列。但我设计的算法有一个缺陷。仅当字符串的字符是唯一的时才有效。
在字符串的字符可能不唯一的情况下,有人可以帮助我扩展算法吗? 到目前为止我的代码:
#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
感谢。
答案 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个排列。