关于递归(全排序perm问题等,待补充)
将集合X的全排序记为perm(X)
所以,对于一组数 r={r1,r2,…rn},记 Ri=r-{ri}。(1<=i<=n)
当 n=1 , perm(r)=(r)
当 n>1,perm(r)= r1perm(R1)+ r2perm(R2)+…+ rnperm(Rn)
R1,R2…再进行分解,不断地将排序的数,即perm(list,k,m)减少,直到剩下一个数,即 k = =m,可从一个递归出来,回到原来的 for循环,再把下一个数与此时的 list(k)交换,再次执行,到 k==m 再回到上一层 for 循环…直到第一层的 for 循环执行完。由此构成一个递归。
代码:
public static void perm(Object []list, int k, int m){
if(k==m){
for(i=0;i<=m;i++) //输出每一趟排序,前面加上数组中不参与排序的其它数
System.out.print(list[i]);
System.out.println();
}
else
for(int i=k; i<=m; i++){ //★★每个子递归都要进行自己的这个for循环
MyMath.swap(list, k, i); // k后面每个数(**包括自己**)都要与它交换位置
perm(list, k+1 ,m);
MyMath.swap(list, k, i);
}
}
整个递归的规模:变小→变大→变小→变大…(不断循环)…
举个栗子:
现在有一组数,list= {5,6,7,8},要求perm(list,0,3)
(★为了更加清晰展现排序过程,下列数字均为实际数字,而非数组下标!★)
第一趟最外层 for 循环:
7,8 //最里层for循环第一次输出
↗
5,6,perm(list,7,8)
↘
8,7 //位置交换,第二次输出
然后 7 和 6 交换
6,8
↗
5,7,perm(list,6,8)
↘
8,6
然后 8 和 6 交换
7,6
↗
5,8,perm(list,7,6)
↘
6,7
以上共产生六组数
结束后进入第二趟最外层 for 循环,因为 总共有四个数要排序,故总共4层
以此类推
可得到perm(list,0,3)
总结,其实这个算法很简单,因为它的每一个子递归都具有完全相同的特质。
从代码段第二个 for 循环段中就可以看的很明显:
每一次 第一个要排序的数到最后一个,依次跟第一个换位置,然后再分解或者输出。
直到剩下一个数,此时就能从这一底层递归跑出来了。
(然后再回去for循环 i++,让下一个数与第一个数交换位置。这层for循环执行完了,再回上层for执行…)
上一篇: 待补充
下一篇: junit使用问题记录(待补充)
推荐阅读