输入一个已经升序的字符数组,打印出该字符串数组中字符串的所有排列。例如:
input: ab cd
output: ab cd
cd ab
其实这个问题等同于例如输入字符串abc,则输出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba
解决这类问题最简单的方法就是采用递归函数:
如果能生成n-1个元素的全排列,就能生成n个元素的全排列。对于只有一个元素的集合,可以直接生成全排列。所以全排列的递归终止条件很明确,只有一个元素时。 基本的代码实现的框架如下所示:
void permute(char *a,int i,int n)
{
int j;
if (i == n)
printf("%s\n",a);
else
{
for (j = i; j <= n; j++)
{
if(a[i] == a[j] && j != i) //为避免生成重复排列,当不同位置的字符相同时不再交换
continue;
swap((a+i),(a+j));
permute(a,i+1,n);
swap((a+i),(a+j)); //backtrack
}
}
同时我们也可以采用迭代的方法来考虑这个问题。参考C++ 的 STL 库中自带了 next_permutation 来实现C语言的next_permutation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int times = 0;
int next_permutation(int n, char **s)
{
/**
* Complete this method
* Return 0 when there is no next permutation and 1 otherwise
* Modify array s to its next permutation
*/
int head_item =0;
int item =0;
int size = n;
char *tmp = NULL;
// find the sub completed list
for (item = size - 1; item > 0; item--) {
if (strcmp(s[item-1], s[item])<0)
{
break;
}
}
if (item == 0) {
// finished
return 0;
} else {
head_item = item - 1;
}
// find the next item:
// The first great than head_item
for (item = size - 1; item > head_item; item--) {
if (strcmp(s[head_item], s[item]) <0) {
break;
}
}
tmp = s[head_item];
s[head_item] = s[item];
s[item] = tmp;
// reverse the sub list
for (item = head_item + 1; item < size; item++, size--) {
tmp = s[item];
s[item] = s[size-1];
s[size-1]= tmp;
}
return 1;
}
int main()
{
char **s;
int n;
scanf("%d", &n);
s = calloc(n, sizeof(char*));
for (int i = 0; i < n; i++)
{
s[i] = calloc(11, sizeof(char));
scanf("%s", s[i]);
}
do
{
for (int i = 0; i < n; i++)
printf("%s%c", s[i], i == n - 1 ? '\n' : ' ');
} while (next_permutation(n, s));
for (int i = 0; i < n; i++)
free(s[i]);
free(s);
return 0;
}
本文介绍了如何使用C语言生成已排序字符数组的所有排列。通过递归和迭代两种方法实现,详细展示了代码实现过程,包括避免重复排列的处理。
1077

被折叠的 条评论
为什么被折叠?



