字母全排列——递归方法
算法分析
设有一字母数组为:
word = {‘a’,‘b’,‘c’,‘d’…}
假设word当前只有四个与元素,分别为a、b、c、d;
如果需要将word数组按照全排列打印的话,则所有的结果有4 * 3 * 2 *1 = 24种排列顺序,分别为:
abcd、abdc、acbd、acdb、adcb、adbc
bacd、badc、bcad、bcda、bdca、bdac
cbad、cbda、cabd、cadb、cdab、cdba
dbca、dbac、dcba、dcab、dacb、dabc
观察排列结果可知
a后面是bcd的全排列
b后面是cd的全排列
……
即可以将题目分解几个不同规模的问题,原理如下图所示:
图片来源
即需要得到以a为开头的所有字母顺序时,求bcd的所有排列顺序即可,以此类推
核心代码分析
for(i = start;i <= end;i++){ //for循环为核心代码
SWAP(list[start],list[i],temp); //交换list[start]和list[i]的值
perm(list,start + 1,end); //进行递归,start+1表示求剩下字母的所有排列顺序
SWAP(list[start],list[i],temp); //还原字母顺序
}
函数SWAP(x,y,t)为宏定义,用于交换x和y的值。
核心代码中含有两个SWAP(x,y,z),且分别在递归调用前和递归调用后。
第一个SWAP(x,y,z)
就拿递归中第一层来说,因为执行到该语句时,已经完成以x为开头的所有字母序列的打印,所以需要置换新的字母作字母序列的首字母。相应得,x就需要参与首字母后面的几个字母的排列。
例如完成已经打印所有以a为首字母的序列时abcd、abdc、acbd、acdb、adcb、adbc
就需要将a和b置换过来,使得a和c、d按照不同顺序排成字母序列连接在b后面,生成以b为首字母的所有字母序列
bacd、badc、bcad、bcda、bdca、bdac
第二个SWAP(x,y,z)
简单来说就是还原字母顺序,使得第一个SWAP(x,y,z)每次置换的结果是使得全排列结果的所有字母序列的首字母是按照原数组中字母顺序排列的。
例如原数组中字母顺序为:a、b、c、d
那么全排列的结果顺序应该为:abcd、abdc、acbd、acdb、adcb、adbc
bacd、badc、bcad、bcda、bdca、bdac
cbad、cbda、cabd、cadb、cdab、cdba
dbca、dbac、dcba、dcab、dacb、dabc
C++代码
/*将字母按照全排列顺序打印*/
#include <iostream>
#define SWAP(x,y,t)((t) = (x),(x) = (y),(y) = (t)) //用于交换两个变量的值
using namespace std;
void perm(char list[],int start,int end){
int i;
char temp;
if(start == end){
for(i = 0;i <= end;i++)
cout<<list[i];
cout<<endl;
}
else{
for(i = start;i <= end;i++){ //for循环为核心代码
SWAP(list[start],list[i],temp); //以已作为首字母出现的字母移动到后面
perm(list,start + 1,end);
SWAP(list[start],list[i],temp); //还原字母顺序
}
}
}
int main(){
char list[4] = {'a','b','c','d'};
perm(list,0,3);
return 0;
}
参考书籍:《数据结构基础》(C语言版)