首页 > 代码库 > 全排列的实现
全排列的实现
1 什么是全排列:例如给出字符串abc: 其全排列为:abc bca cba acb bac cab; 对于acc则全排列为 acc cac cca
2 下面看一下非递归的实现方法:以1234 为例从右向左找相邻递增(严格递增)的数对: 34 满足条件,把3记为一个交换点。 在从右向左找第一个大于第一个交换点的数为4作为第二个交换点,交换后得:1243;然后把第一个交换点后的序列逆序。3只有一个无需逆序;然后继续下一次:43不满足,24,满足, 第一个大于2的数为3 ,交换1342,逆序最后两个:1324;依此类推:下一个1342,再下一个1423.....在排列之前先对数组进行排序:
程序实现如下:
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<string>
using namespace std;
void swap(char &a, char &b)
{
int temp=a;
a=b;
b=temp;
}
char *sort(char *s)
{
int len(strlen(s)),i(0),j(0);
for(i=0;i<len-1;i++)
{
for(j=i+1;j<len;j++)
{
if(*(s+j)<*(s+i))
swap(*(s+j),*(s+i));
}
}
return s;
}
bool fullrange(char *s)
{
int len=strlen(s);
char *p1,*p2,find;
p1=s+len-1;//point to the last one
p2=s+len-2;//
while(*p2>=*p1 && p2>=s) //找递增有序对,从右向左。
{
--p1;
--p2;
}
if(p1==s)
{
return false;
}
p1=s+len-1;
while(*p1<=*p2) //找大于交换点的最小值。
{
--p1;
}
// find=*p1;
// *p1=*p2;
// *p2=find;
swap(*p1,*p2);
++p2;
p1=s+len-1;
while(p1>p2)//逆序
{
// find=*p1;
// *p1=*p2;
// *p2=find;
swap(*p1,*p2);
++p2;
--p1;
}
return true;
}
void fullrange_show(char *s)
{
//fastsort(s);
// cout<<s<<endl; //输出当前序列
bool sw=1;//fullrange(s);
while(sw)
{
cout<<s<<endl; //输出当前序列
sw=fullrange(s);//得到下一个
}
}
int main(int argc, char *argv[] )
{
if(argc!=2)
{
cout<<"Usage: ./fullrange string"<<endl;
return 1;
}
// char temp[]="aacc";
// fastsort(temp);
fullrange_show(sort(argv[1]));
return 0;
}
3 递归的实现方法:给出abc,从第一个元素起依此与后面的元素交换,得到一组新的数列,包括原数列。然后第二个元素在于其后面的元素依此交换,一直循环到最后一个元素。对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
用编程的话描述就是第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数。下面给出完整代码:
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<string>
using namespace std;
void swap(char &a, char &b)
{
int temp=a;
a=b;
b=temp;
}
char *fastsort(char *s)
{
int len(strlen(s)),i(0),j(0);
for(i=0;i<len-1;i++)
{
for(j=i+1;j<len;j++)
{
if(*(s+j)<*(s+i))
swap(*(s+j),*(s+i));
}
}
return s;
}
bool fullrange(char *s)
{
int len=strlen(s);
char *p1,*p2,find;
p1=s+len-1;//point to the last one
p2=s+len-2;//point to the head one
while(*p2>=*p1 && p2>=s)
{
--p1;
--p2;
}
if(p1==s)
{
return false;
}
p1=s+len-1;
while(*p1<=*p2)
{
--p1;
}
// find=*p1;
// *p1=*p2;
// *p2=find;
swap(*p1,*p2);
++p2;
p1=s+len-1;
while(p1>p2)
{
// find=*p1;
// *p1=*p2;
// *p2=find;
swap(*p1,*p2);
++p2;
--p1;
}
return true;
}
void fullrange_show(char *s)
{
//fastsort(s);
// cout<<s<<endl;
bool sw=1;//fullrange(s);
while(sw)
{
cout<<s<<endl;
sw=fullrange(s);
}
}
bool IsSwap(char *pszStr, int nBegin, int nEnd)
{
for (int i = nBegin; i < nEnd; i++)
if (pszStr[i] == pszStr[nEnd])
return false;
return true;
}
//k表示当前选取到第几个数,m表示共有多少数.
void AllRange(char *pszStr, int k, int m)
{
if (k == m)
{
static int s_i = 1;
printf(" 第%3d个排列\t%s\n", s_i++, pszStr);
}
else
{
for (int i = k; i <= m; i++) //第i个数分别与它后面的数字交换就能得到新的排列
{
if (IsSwap(pszStr, k, i))
{
swap(*(pszStr + k), *(pszStr + i));
AllRange(pszStr, k + 1, m);
swap(*(pszStr + k), *(pszStr + i));
}
}
}
}
void Foo(char *pszStr)
{
AllRange(pszStr, 0, strlen(pszStr) - 1);
}
int main(int argc, char *argv[] )
{
if(argc!=2)
{
cout<<"Usage: ./fullrange string"<<endl;
return 1;
}
// char temp[]="aacc";
// fastsort(temp);
fullrange_show(fastsort(argv[1]));
cout<<"-----------------"<<endl;
// char temp[strlen(argv[1])];
// fullrange_r(argv[1],0,strlen(argv[1])-1);
Foo(argv[1]);
return 0;
}