来源:http://blog.youkuaiyun.com/morewindows/article/details/7370155
/*
1.全排列就是从第一个数字起每个数分别与它后面的数字交换。
2.去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
3.全排列的非递归就是由后向前找替换数和替换点,然后由后向前找第一个比替换数大的数与替换数交换,
最后颠倒替换点后的所有数据。
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
void Swap(char *a, char *b)
{
char t = *a;
*a = *b;
*b = t;
}
bool IsSwap(char * pszStr, int begin, int end)
{
for(int i = begin; i < end; i ++)
if(pszStr[i] == pszStr[end])
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 permutation(char * pStr)
{
AllRange(pStr, 0, strlen(pStr) - 1);
}
void Reverse(char * a, char * b)
{
while(a < b)
Swap(a ++, b --);
}
bool Next_permutation(char a[])
{//下一个排列
char *pEnd = a + strlen(a);
if (a == pEnd)
return false;
char *p, *q, *pFind;
pEnd--;
p = pEnd;
while (p != a)
{
q = p;
--p;
if (*p < *q) //找降序的相邻2数,前一个数即替换数
{
//从后向前找比替换点大的第一个数
pFind = pEnd;
while (*pFind <= *p)
--pFind;
//替换
Swap(pFind, p);
//替换点后的数全部反转
Reverse(q, pEnd);
return true;
}
}
Reverse(p, pEnd);//如果没有下一个排列,全部反转后返回true
return false;
}
int main()
{
char str1[] = "231";
permutation(str1);
char str2[] = "231";
do{
printf("%s\n", str2);
}while(Next_permutation(str2));
printf("\n\n");
char str3[] = "231";
do{
printf("%s\n", str3);
}while(next_permutation(str3, str3 + strlen(str3)));
return 0;
}