字母全排列——递归方法

算法分析

 设有一字母数组为:

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的全排列
……

 即可以将题目分解几个不同规模的问题,原理如下图所示:
      https://www.cnblogs.com/nowornever-L/p/6008954.html图片来源

 即需要得到以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语言版)

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值