java 全排列 非递归,非递归和递归实现全排列

C

非递归 思路 递归的解题方法有时间另开一文叙述,这里要介绍的是非递归的思路。还是同样的以数字集合{1,2,3}为例。 这个集合生成的有序序列集合中的第一个序列是1 2 3,这个很容易能够看出。问题是如何根据该序列生成下一个有序的序列呢?下一个有序序列在字典序上刚刚好大于前一个序列,应该是1 3 2,可用看出是将第一个序列中的2和3交换位置得到。而1 3 2之后的下一个序列是2 1 3,是将最后一个2放到了1的前面。在2 1 3之后是2 3 1,是在2 1 3的基础上将最后的3换到了1的前面。一个很直观的感觉就是从后向前查找,遇到合适的数的时候与前面某一个数字交换。 具体算法描述,以数字集合{1,2,3}为例: 1,第一个序列就是当前集合元素连起来本身。 2,从后向前查找后面的数大于前面的数对(从小到大,称其为逆序对),找不到说明所有的排列均已经生成(即从123到了321),若找到(例如2 1 3中的 1和3就是一个逆序对)则停下来。 3,以213为例,就是记住3的位置为i,再从后向前查找数,要找到刚刚好大于1(位置为i-1)的数,这里很显然还是3。 4,交换第三步找到的数与位置为i-1的数。 5,逆置从位置i开始到集合结尾的所有的数,例如从*****321(位置i为3)到*****123(位置i为1)。 6,重复这一过程,直到找不到逆序对,则生成了所有的序列。

#include

void swap(int *p,int*q)

{

int tmp;

tmp=*p;

*p=*q;

*q=tmp;

}

void mknewseq(int *data,int start, int last)

{

while(start

{

swap(&data[start],&data[last]);

start++;

last--;

}

}

void showdata(int *data,int num)

{

int i=0;

for(i=0;i

{

printf(" %d ",data[i]);

}

printf("\n");

}

int findall(int *data,int num)

{

int i,j;

int lastdata=num-1;

int tmp;

for(i=lastdata;i>0;i--)

{

if(data[i]>data[i-1]) break;

}

if(0==i) return 0;

tmp=i;

for(j=lastdata;j>=i;j--)

{

if((data[j]>data[i-1])&&(data[j]

tmp=j;

}

swap(&data[tmp],&data[i-1]);

mknewseq(data,i,lastdata);

return 1;

}

int main()

{

int data[4]={1,2,3,4};

showdata(data,4);

while(findall(data,4)){

showdata(data,4);

}

return 0;

} 运行结果:

1 2 3 4

1 2 4 3

1 3 2 4

1 3 4 2

1 4 2 3

1 4 3 2

2 1 3 4

2 1 4 3

2 3 1 4

2 3 4 1

2 4 1 3

2 4 3 1

3 1 2 4

3 1 4 2

3 2 1 4

3 2 4 1

3 4 1 2

3 4 2 1

4 1 2 3

4 1 3 2

4 2 1 3

4 2 3 1

4 3 1 2

4 3 2 1

递归

#include

void perm(int* data, int n, int curr)

{

if (curr==n-1)

{

for (int i = 0; i < n; ++i)

printf("%d", data[i]);

printf("\n");

}

else

{

for (int i = curr; i < n; ++i)

{

int t;

t = data[curr], data[curr] = data[i], data[i] = t;

perm(data, n, curr+1);

t = data[curr], data[curr] = data[i], data[i] = t;

}

}

}

int main()

{

int array[] = {1,2,3};

perm(array, sizeof(array)/sizeof(array[0]), 0);

return 0;

}

123

132

213

231

321

312

Press any key to continue

public class AllPermutation

{

public static void main(String[] args)

{

//使用递归完成全排列

char[] source=new char[]{'A','B','C'};

char[] result=new char[source.length];

allPermutation(0,source,result);

}

/**

*

* @param index当前考虑的数的下标(从0开始)

* @param source

* @param result

*/

public static void allPermutation(int index,char[] source,char[] result){

//当源数据中只有一个字符时,将该字符加入结果数组,并输出

if(source.length==1){

result[index]=source[0];

show(result);

return ;

}

for(int i=0;i

result[index]=source[i];

char[] newSource=getNewSource(source,source[i]);

allPermutation(index+1, newSource,result);

}

}

public static void show(char[] result){

System.out.println(result);

}

/**

* 生成去掉指定字符的新源数据数组

* @param source 原来的源数据数组

* @param c 指定去掉的字符

* @return

*/

public static char[] getNewSource(char[] source,char c){

char[] newSource=new char[source.length-1];

for(int i=0,j=0;i

if(source[i]!=c){

newSource[j]=source[i];

j++;

}

}

return newSource;

}

}

Java

package com.syj.csdn;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

/**

*

* Title:全排列算法

*

*

*

* Copyright: http://blog.csdn.net/sunyujia/

*

*

* @author 孙钰佳

* @main sunyujia@yahoo.cn

* @date 2009-04-25 23:57:23 PM

*/

public class FullSort {

//将NUM设置为待排列数组的长度即实现全排列

private static int NUM = 3;

/**

* 递归算法:将数据分为两部分,递归将数据从左侧移右侧实现全排列

*

* @param datas

* @param target

*/

private static void sort(List datas, List target) {

if (target.size() == NUM) {

for (Object obj : target)

System.out.print(obj);

System.out.println();

return;

}

for (int i = 0; i < datas.size(); i++) {

List newDatas = new ArrayList(datas);

List newTarget = new ArrayList(target);

newTarget.add(newDatas.get(i));

newDatas.remove(i);

sort(newDatas, newTarget);

}

}

public static void main(String[] args) {

String[] datas = new String[] { "a", "b", "c", "d" };

sort(Arrays.asList(datas), new ArrayList());

}

}

python

def permutations(iterable, r=None):

# permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC

# permutations(range(3)) --> 012 021 102 120 201 210

pool = tuple(iterable)

n = len(pool)

r = n if r is None else r

if r > n:

return

indices = range(n)

cycles = range(n, n-r, -1)

yield tuple(pool[i] for i in indices[:r])

while n:

for i in reversed(range(r)):

cycles[i] -= 1

if cycles[i] == 0:

indices[i:] = indices[i+1:] + indices[i:i+1]

cycles[i] = n - i

else:

j = cycles[i]

indices[i], indices[-j] = indices[-j], indices[i]

yield tuple(pool[i] for i in indices[:r])

break

else:

return

参考: [1] .

http://blog.csdn.net/syzcch/article/details/8136218 [2].

http://bbs.csdn.net/topics/220058319 [3].

http://blog.csdn.net/sunyujia/article/details/4124011 [4].

http://docs.python.org/2/library/itertools.html#itertools.permutations

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值