问题:
用蛮力法生成{1,2...,n}的所有n!个排列。
例:
开始 1
插入 2 12 21
插入3 123 132 312 213 231 321
伪代码:
1.生成初始排列{1};
2.for(i=2;i<=n;i++)
for(j=1;j<=(i-1)!;j++)
for(k=i;k>=1;k--)
算法实现(C++):将i插入到第j个排列中的第k个位置;
/*蛮力法解决全排列问题*/ #include<iostream> #include<string> using namespace std; void insert(char c1[], char c2[], char c, int i) //将c 插入c1 并将c1复制到c2 { int j; for (j = 0; j < i; j++) c2[j] = c1[j]; c2[i] = c; for (j = i + 1; j <= strlen(c1) + 1; j++) c2[j] = c1[j - 1]; } void perml(int n)//为生成排列集合元素的个数 { int i, j, k, m = 1; char **c[2];//采用两个字符序列存储,分别存储i-1和i的全排列 c[1] = new char*[1]; c[1][0] = new char[2]; c[1][0][0] = '1'; c[1][0][1] = 0; for (i = 2; i <= n; i++) { m = m*(i - 1); c[i % 2] = new char*[m*i]; for (j = 0; j < m; j++) { for (k = 0; k < i; k++) { c[i % 2][j*i + k] = new char[i + 1]; insert(c[(i + 1) % 2][j], c[i % 2][j*i + k], char(i + '0'), k); } delete[] c[(i + 1) % 2][j]; } delete[] c[(i + 1) % 2]; } for (i = 0; i < m*n; i++) { cout << "第" << i + 1 << "排列:" << c[n % 2][i] << endl; delete[] c[n % 2][i]; } } int main() { perml(3); return 0; }
运行结果:
递归方法--减治法
当数列{ 1, 2, 3},需要生成全排列,总共会有3个位置,
当3在位置3时,排列为: {1, 2, 3},{2, 1, 3} ,相当与 求 {1,2} 让后再加上 3
当2在位置3时,排列为: {1, 3, 2},{3, 1, 2} ,相当与 求 {1,3} 让后再加上 2
当1在位置3时,排列为: {3, 2, 1},{2, 3, 1} ,相当与 求 {3,2} 让后再加上 1
这样可以每次减少少一个数,然后求剩余数的全排列。
代码如下:
#include <iostream>
using namespace std;
void Permutation(int num[], int count, int size)
{
if (size <= 1) //一个数的全排列就是自己本身不需要继续求解
{
for (int i = 0; i < count; ++i)
{
cout << num[i] << " ";
}
cout << endl;
return;
}
int temp;
for (int i = size - 1; i >= 0; --i)
{
//把当前数字与最后一个数字交换,
temp = num[i];
num[i] = num[size - 1];
num[size - 1] = temp;
Permutation(num, count, size - 1);//每次减少最后一个数字
//将数列恢复到交换前的状态
temp = num[i];
num[i] = num[size - 1];
num[size - 1] = temp;
}
}
int main()
{
int num[] = { 1,2,3 };
Permutation(num, sizeof(num) / sizeof(int), sizeof(num) / sizeof(int));
return 0;
}
结果: