插入函数:
char** insert(char*a, char character_cnt, char chara)
{
char** ret = new char*[character_cnt + 1];
int copy_pre;
for (int i = 0; i < character_cnt + 1; i++)
ret[i] = new char[character_cnt + 1];
for (int i = 0; i < character_cnt + 1; i++) //character_cnt+1个待插位置,对应[O before],[1 before]…[character_cnt-1 before]
{
for (copy_pre = 0; copy_pre < i; copy_pre++)
ret[i][copy_pre] = a[copy_pre];
int a_copy_after_start = copy_pre;
ret[i][copy_pre] = chara;
copy_pre++;
for (; a_copy_after_start < character_cnt; a_copy_after_start++, copy_pre++)
ret[i][copy_pre] = a[a_copy_after_start];
}
return ret;
}
求全排列:
char** f(char* a,int character_cnt)
{
int tmp = 1, out_pos = 0, sum = 0;
int* stdOFFSET = new int[character_cnt];
//k=1 k=2
stdOFFSET[0] = 0;
stdOFFSET[1] = 0;
for (int i = 2; i < character_cnt; i++) //k=3… character_cnt
{
int mul = 1;
for (int j = 1 ; j <= i ; j++) mul *= j;
sum += mul;
stdOFFSET[i] = sum;
}
///
int tmpsum = 0;
for (int i = 1; i <= character_cnt; i++) //1 2 3 4
{
int mul = 1;
for (int j = 2; j <= i; j++)
mul *= j;
tmpsum += mul;
}
char** p = new char*[tmpsum - 1];
for(int i = 0; i < tmpsum; i++)
{
p[i] = new char[character_cnt+1];
memset(p[i], 0, sizeof(*p[i])*character_cnt+1);
}
//
p[0][0] = a[0];
for (int k = 1 ; k < character_cnt ; k++) //从两位字符开始
{
for (int m = 0; m < tmp; m++)
{
char** pout = insert(p[m + stdOFFSET[k - 1]], k, a[k]);
for (int j = 0; j < k + 1; j++)
memcpy(p[out_pos++], pout[j], k + 1);
}
tmp *= (k + 1); //2->6->24,分裂后个数
}
return p + out_pos;
}
测试代码:
int _tmain(int argc, _TCHAR* argv[])
{
char A[]={"abcdefgh"};
char** x = f(A,strlen(A)); //x指向计算结果的最后位置
for (int i = 1*2*3*4*5*6*7*8; i > 0 ; i--)
cout << 1*2*3*4*5*6*7*8-i << " : " << *(x-i) << endl;
}
基本思想为依次从字符串中取数,每取一个数,往现有计算结果的各个位置插入,无需迭代,易于理解
但与递归法求全排列相比,需要消耗一定的堆空间。