來源:http://blog.csdn.net/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;
}