1.问题
求n个元素的全排列
2.分析
n=1时:
a1
n=2时:
a1 a2
a2 a1
n=3时:
a1 a2 a3
a1 a3 a2
a2 a1 a3
a2 a3 a1
a3 a2 a1
a3 a1 a2
在n=3时,得到6种全排列,从上到下两两分组可以得到3组,可以发现下面的规律:
-
第一组以
a1
开始,之后连接a2和a3
的全排列,以此类推。 -
将第一组的
a1与a2
交换位置可以得到第二组,将第一组的a1与a3
交换位置可以得到第三组。
那么可以找到递归调用:在n
个有序元素中,第一个元素连接后n-1
个元素的全排列;将第1
个元素与第2
个元素互换,继续连接后n-1
个元素的全排列;以此类推… …;最终将第n-1
个元素与第n
个元素互换。当后n-1
个元素只剩一个时,就打印整个有序元素序列。
3.实现(C++)
/**< 递归求解全排列问题 */
#include <iostream>
#include <stdio.h>
#include<string>
using namespace std;
#define ARRAY_LEN 3 //定义数组长度
//用于打印字符数组a
void print_array(char a[])
{
for(int i=0; i<ARRAY_LEN; i++) printf("%c",a[i]);
printf("\n");
}
//用于打印缩进
void print_tab(int n){
string str="";
for(int i=0;i<n;i++) str+="\t";
cout<<str;
}
// 求字符数组a[0:n-1]中所有字符从下标k到n-1的全排列
void range(char a[],int k,int n)
{
print_tab(k);
printf("当前调用的是range(a,%d,%d):\n",k,n);
if(k==n)
{
print_tab(k);
printf("目标输出-----------------");
print_array(a);
}
else
{
for (int i=k; i<n; i++)
{
//打印信息
print_tab(k);
printf("a[%d]与a[%d]交换,交换前数组a为:",k,i);
print_array(a);
//交换
char temp=a[i];
a[i]=a[k];
a[k]=temp;
//打印信息
print_tab(k);
printf("交换后数组a为:");
print_array(a);
//递归调用
range(a,k+1,n);
//复原
temp=a[i];
a[i]=a[k];
a[k]=temp;
//打印信息
print_tab(k);
printf("复原后数组a为:");
print_array(a);
}
}
//打印信息
print_tab(k);
printf("range(a,%d,%d):调用结束\n",k,n);
}
int main()
{
char a[ARRAY_LEN]= {""};
//初始化字符数组a[n]为字母表顺序的大写字母
for(int i=0; i<ARRAY_LEN; i++) a[i]= 65+i;
//主函数调用
range(a,0,ARRAY_LEN);
return 0;
}
4.结果
当n=2时,可以清晰看到整个调用过程:
n>2时就可以删去打印信息的部分(眼花缭乱)…
/**< 递归求解全排列问题 */
#include <iostream>
#include <stdio.h>
#include<string>
using namespace std;
#define ARRAY_LEN 3 //定义数组长度
//用于打印字符数组a
void print_array(char a[])
{
for(int i=0; i<ARRAY_LEN; i++) printf("%c",a[i]);
printf("\n");
}
// 求字符数组a[0:n-1]中所有字符从下标k到n-1的全排列
void range(char a[],int k,int n)
{
if(k==n)
{
printf("目标输出-----------------");
print_array(a);
}
else
{
for (int i=k; i<n; i++)
{
//交换
char temp=a[i];
a[i]=a[k];
a[k]=temp;
//递归调用
range(a,k+1,n);
//复原
temp=a[i];
a[i]=a[k];
a[k]=temp;
}
}
}
int main()
{
char a[ARRAY_LEN]= {""};
//初始化字符数组a[n]为字母表顺序的大写字母
for(int i=0; i<ARRAY_LEN; i++) a[i]= 65+i;
//主函数调用
range(a,0,ARRAY_LEN);
return 0;
}