c语言函数训练之全排列 c语言 全排列

C语言的全排列问题!急!这其实是一个递归
递归函数
意思是这样的
比如有n个数
1
2. 。。。n
把1
从第一个开始
往后
与每个数开始交换
然后
第一个数就算定了
后面的
第2个到第n个当成一个整体
再进行这个函数递归
也就是说
第二个到第n个进行全排列
这样下去
当全排列到最后一组数
即第n个数一个的时候
递归退出条件就出来了
就可以输出全排列的值了
当然
最后别忘记把交换的数还原
再进行下一次交换
递归哦
所以最后一局的交换也是很重要的
听完我的解释
再好好琢磨一下
相信你一定会明白的
要是还是不懂可以继续追问我
用c语言编写全部排列void chang(char str[],int m)/*定义循环左移函数(我没有用左移函数)*/
{
int i,j;
char temp=str[0];
for (i=0;im;i++) str[i]=str[i+1];
str[i]=temp;
}
void pai(char str[],int m,int n) /*定义全排列函数*/
{
int k;
void chang(char str[],int m);
if (mn)/* 定 义 递 归 调 用 出 口*/
{
for (k=0;k=m;k++)
{
pai(str,m+1,n); /*递归调用*/
chang(str,m); /*调用左移函数*/
}
}
else printf("%s\t",str);
}
#include "stdio.h"
main()
{char str[]="ABCD"; /*全排列字符,可以任意多个(相应的下面排列函数中参数"4"改成全排列字符的个数)*/
clrscr();
pai(str,0,4); /*这里参数0(下标)表示从第一个元素开始,4表示元素个数(不是下标)*/
getch();
}
C语言怎么实现有重复元素的全排列?整体思路就是利用回溯的思想,也可认为是深度优先搜索
从字符串第一位idx=0开始,每次递归都从s[idx]之后选择一个字符与s[idx]交换
因为可能有重复字符 , 可使用哈希数组标记当前循环每个字符是否被选择
因为字符范围不超过ASCII码,所以使用128空间的数组足够用来标记了
选择好当前字符s[i]并与s[idx]交换之后,递归调用继续排列下一位s[idx+1]
注意这里要进行回溯 , 即不选s[i]而选择之后的某个字符交换到s[idx]
所以要将之前的s[i]与s[idx]交换过来,恢复原状,才能循环判断下一个选择
具体代码截图如下:
运行结果如下:
结果正确,望采纳~
附源码:
#include stdio.h
#include stdlib.h
#include string.h
#define MAXN 1000000 // 排列总数可能很多
int num = 0; // 记录排列总数
char *res[MAXN] = {NULL}; // 指针数组保存排列结果
void swap(char *x, char *y) { // 交换两个字符变量的内容
char ch = *x;
*x = *y;
*y = ch;
}
void perm(char *s, int n, int idx) { // 回溯产生字符串全排列
if (idx == n) { // 已排列到字符串结尾
res[num] = (char *)malloc(sizeof(char) * (n + 1));
//printf("%s\n", s); // 输出当前排列
strcpy(res[num], s); // 保存当前排列
num++; // 排列总数加1
return;
}
int i, hash[128] = {0}; // 哈希数组 , 标记每个字符是否被选择
for (i = idx; in; i++) {
if (hash[s[i]] == 1)
continue; // 跳过已被标记过的重复字符
hash[s[i]] = 1; // 选过的话在数组中标记为1
swap(s[idx], s[i]); // 选择s[i]交换到s[idx]
perm(s, n, idx + 1); // 递归,继续s[idx+1]的选择
swap(s[idx], s[i]); // 回溯,当前不选择s[i],而选择其他字符
}
}
int main() {
int n, i;
scanf("%d", n);
char *s = (char *)malloc(sizeof(char) * (n + 1));
scanf("%s", s);
perm(s, n, 0);

推荐阅读