C语言字母排列组合的实现.doc
C语言字母排列组合的实现曹玉坤2011-6-21目录概述3需求3规律3实现算法5难点6代码6概述 本文档概述字母排列组合的实现算法和分析过程,着重强调在解决问题前,对问题的思考方法;注重研究问题的思路。从问题需求开始详述解决问题的过程。需求我们要解决的问题是,在26个字母中取出任意多个进行排列组合并把他们的组合方式打印出来。并要求用递归的方式实现。规律 从要求中可以看出,需要使用递归的方式来解决问题。这是对我们很好的提示。大家知道递归时用在fn和fn-1之间有计算关系的,也就是说通过对fn-1的计算处理就能够得到fn的结果。最终在n等于某个具体的数值时,我们能确切的算出fn的值,也就是要给我们一个基点。 通过以上分析,就明确了我们的需要做的工作第一,我们要找到fn和fn-1之间的规律;第二我们要找出那个基点,也就是能确切给出fn值的点。 我们先来看看下面的字母排列 a baab cbacabbcaacbbacabc dcbadcabdbcadacbdbacdabccdbacdab 大家从上面的例子看出来规律没有相信大家从上面的排列中一眼就能看出各个数列直接的关系,那就是新添字母总是按照顺序插入到原有排列的之间。如第一列是a, 第二列就是新添字母b先添加到排列a的前面,然后再排列到a的后面,这样就形成了第二行的排列ba ab。第三行排列如规律c先排列到ba的前面,c 再排列到ab的前面,下来c排列到b后a前形成bca, 其次c排列到ab的中间形成acb;接着c又排到ba后面,形成bac, 然后c再排列到ab后面形成abc。这样我们就得到了第三行的字母排列。相信大家已经会按规律排列第四行的字母排列了。 规律已经找到,那么我们选择几个字母作为基点呢如上图排列,我们可以轻松的罗列出来一个字母时的排列,两个字母时的排列,三个字母时的排列,四个的时候,虽然我们也能根据规律将其罗列出来,但已经比较麻烦了。那么我们的基点必然就是选择n1,2,3中的一个了。到底哪一个,现在先不讲,看完后面的大家就明白了怎样选取递归用的基点。 实现算法 上一节我们已经分析了递归用的fn和fn-1之间的规律。现在我们看看递归中基点的选取。我们举个例子来说明,字母为a、b、c、d、e、f、g、h、i、g.等等,首先看f1a; f2ba, ab; f3cba,cab,bca,acb,bac,abc。我们看看先哪个做基点比较好。 首先我们假定以f1为基点。f1char 1a那么相对于f2应该怎么算呢因为数组必须初始化长度,所以这里我们用到malloc动态申请存储空间。这样我们先计算要申请空间的大小。N个不同字母组成个数为PnN,总长度应为N*N。f2的空间为2*1*24。应该动态申请长度为4的char空间。第一步,先用b排在a的前面,让然后让b排在a的后面。得到ba,ab。第二不我们通过f2生成f3,首先我们申请f3的空间,3*318,再根据f2生成f3。首先在f2的基础上将c,先插入到每个数列的第一位,然后是第二位,然后是最后一位。我们得到的递归方法是,先将申请到的空间以n分割为n个,fn-1以n-1分成(n-1)个,首先将第n个字母排在fn-1每个组的前面,这样就组成第一组n的排列,然后依次放到第二位,第三位。这样就生成了fn。 以f2,f3做为基点的原理同上,只是人工计算出基点以前的排列组合。而不是用递归的方法。难点 本问题的难点在于怎样选择正确的新字母的插入点和对动态申请的空间进行释放。 对于正确找出插入字母的位置,我们的要求是第一次插入到最前面即第0为,第二次插入到1的位置,第三次插入到第2的位置,最后一次插入到n的位置。大家一定想到了取模,这是个很好的方法,不过有个问题那就是0和n的时候我们取模都是0,所以要加个判断,看是否是第一次插入。 第二个问题我们就要介绍free函数,这个函数是用来释放malloc申请的空间的,提供给我们一个特性,那就是只要给出要求释放空间的首地址,它就能将此段空间释放。那么我所做的就是要在每次函数的时候返回申请空间的首地址。代码代码是以长度为7做样例的。include stdio.hinclude stdlib.hchar *testchar *source, unsigned int n;define LEN 7mainchar *t;char strLENa,b,c,d,e,f,g tteststr,LEN; fori1;iLEN1;ilengthlength*i;fori0;iLEN*length;iifiLEN0printft;ifiLEN*LEN0printfn;printfc,ti; printfn; ifLEN1freet;tNULL;char* testchar *source, unsigned int nchar *pNULL;char *preResultNULL;char *preSourceNULL; unsigned int num0;unsigned int count0,i0,j0;unsigned int length1;ifn2cotains;forj1;jn1;jlengthj*length;printfdt,length;preSourcesource1;pchar*mallocsizeofchar*n*length; preResulttestpreSource,n-1;return 0;forcount0; countn; countifcountn-1 fori0;in-1*length/n;i ifin-1count pnumsource0; num; pnumpreResulti; num; elsefori0;in-1*length/n;i if0i pnumpreResulti; num; continue; ifin-10 pnumsource0; num; pnumpreResulti; num; pnumsource0;freepreResult;preResultNULL;return p;else if2n pchar *mallocsizeofchar*4;p0source0;p1source1;p2source1;p3source0; freesource; return p;elsereturn source;