分析:为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。
根据规律,可以列出递归伪代码:
allArrange(str,k,m)
{
if k==m print;
for i=k to m {
swap(str,k,i); //k为第k个数
allArrange(str,k+1,m);
swap(str,k,i);} //注意,因为递归有回溯的过程,所以需要把数字重新调换回来变为”初始“的排列。
}
程序代码如下:
#include<stdio.h>
#include<string.h>
void swap(char *a,char *b){
char temp = *a;
*a = *b;
*b = temp;
}
void Allarrange(char *str,int k,int len){
int i;
if(k==len){
static int s_i=1;
printf("第%d种排列为:\t%s\n",s_i++,str);
}
else{
for(i=k;i<=len;i++){
swap(str+i,str+k);//第i个和第k个元素交换位置
Allarrange(str,k+1,len);//调用全排列
swap(str+i,str+k);// 再将两个元素调换回来
}
}
}
int main(){
char str[10];
printf("请输入排列的字符串:");
gets(str);
Allarrange(str,0,strlen(str)-1);//递归调用全排列函数 0~n-1
return 0;
}
递归的过程不易理解,可以画递归树帮助理解。以"123"为例:
而去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。用编程的话描述就是第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数。
下面给出完整代码:
#include<stdio.h>
#include<string.h>
int IsSame(char *str,int s_First,int s_End){
int i;
for(i = s_First ; i < s_End ; i++){
if(str[i]==str[s_End])
return 0;
}
return 1;
}
void swap(char *a,char *b){
char temp = *a;
*a = *b;
*b = temp;
}
void Allarrange(char *str,int k,int len){
int i;
if(k==len){
static int s_i=1;
printf("第%d种排列为:\t%s\n",s_i++,str);
}
else{
for(i=k;i<=len;i++){
if(IsSame(str,k,i)){
swap(str+i,str+k);
Allarrange(str,k+1,len);
swap(str+i,str+k);
}
}
}
}
int main(){
char str[10];
printf("请输入排列的字符串:");
gets(str);
Allarrange(str,0,strlen(str)-1);
return 0;
}
————————————————
版权声明:本文为优快云博主「苍之羽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_42552533/article/details/88606550https://blog.youkuaiyun.com/qq_42552533/article/details/88606550https://blog.youkuaiyun.com/qq_42552533/article/details/88606550
补充C++代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int sum=0;
int main(){
int a[6]={0,1,2,3,4,5};
do{
for(int i=0;i<6;i++)
cout<<a[i];
cout<<endl;
sum++;
}while(next_permutation(a,a+6));
cout<<sum;
return 0;
}