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 <stdio.h>

void swap(int *p,int*q)
{
	int tmp;
	tmp=*p;
	*p=*q;
	*q=tmp;
}

void mknewseq(int *data,int start, int last)
{
	while(start<last)
	{
		swap(&data[start],&data[last]);
		start++;
		last--;

	}
}

void showdata(int *data,int num)
{
	int i=0;
	for(i=0;i<num;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]<data[tmp]))
			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
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 <stdio.h>
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.length-index;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<source.length;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;

/**
 * <p>
 * Title:全排列算法
 * </p>
 *
 * <p>
 * Copyright: 
 * </p>
 *
 * @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());
	}

}
package com.syj.csdn;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * Title:全排列算法
 * </p>
 *
 * <p>
 * Copyright: 
 * </p>
 *
 * @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
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