全排列递归算法http://blog.csdn.net/u014599786/article/details/23170749
(2)字典序法
对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。如{1,2,3}的排列中,132排在123之后,排在213之前。
算法思路:
1.如对于{1,2,3,4,5}的一个排列p1为list[]={1,3,4,6,5,2},要求出下一个排列,首先要从最右边开始,向左找到第一个左边的数小于右边的数的位置i,在p1中为46即i=2号位置(下标从0开始);
2.再从最右边开始,找到比list[i]大的数中最小者的位置j,因为list中的数是按字典序排序的,所以list[i]以后的数组元素是从大到小排列的,所以j即为从最右边开始第一个比list[i]大的数的下标,p1为5中j=4;
3.交换list[i]、list[j]后list[]={1,3,5,6,4,2},此时5后面的数是从从大到小排列的,所以按字典序的下一个排列应该把后面的数倒转,既得到下一个排列list[]={1,3,5,2,4,6}
完整算法:
#include <cstdlib>
#include <iostream>
using namespace std;
int list[100], n;
//交换数组两个元素
void swap(int i, int j)
{
int temp;
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
//将数组逆序
void reverse_list(int i)
{
int j, k;
for(k = i+1, j = n-1; j > k; j--, k++)
swap(j, k);
}
//输出数组
void print_list()
{
for(int i = 0; i < n; i++)
cout<<list[i]<<" ";
cout<<endl;
}
//按字典序输出全排列
void next_perm()
{
int i, j, total = 0;
if(n == 1){
print_list();
return;
}
while(1){
print_list();
total++;
//从最右边开始,找第一个左边小于右边的数的位置
for(i = n-2; i >= 0; i--)
if(list[i] < list[i+1]) break;
// 没有逆序对结束
if(i < 0) break;
//从最右边开始,找到第一个比list[i]小的数
for(j = n-1; j > i ;j--)
if(list[j] > list[i]) break;
swap(j, i);
//将位置i后面的数组元素逆序
reverse_list(i);
}
cout<<total<<endl;
}
int main()
{
while(cin>>n){
for(int i = 0; i < n;)
list[i] = ++i;
next_perm();
}
system("PAUSE");
return 0;
}