生成排列 --- 蛮力法,Johnson-Trotter算法
蛮力法
- 思路:
通过递归遍历所有的排列方式。 - 代码演示:
#include <iostream>
using namespace std;
const int MAXSIZE = 100;
int n;
int arr[MAXSIZE];
int visit[MAXSIZE];
int x = 0;
int recursion(int m)//已经排了m个数
{
if (n == m)//已经排了n个数
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";//输出
}
cout << endl;
}
else
{
for (int i = 1; i <= n; i++)
{
if (visit[i] == 0)
{
visit[i] = 1;//标记已选择
arr[x++] = i;//将i放进arr数组
recursion(m + 1);//标记已经排了m+1个数
//回溯
x--;
visit[i] = 0;
}
}
}
return 0;
}
int main()
{
memset(arr, 0, sizeof(arr));
memset(visit, 0, sizeof(visit));
cout << "请输入n的值:";
cin >> n;
recursion(0);
return 0;
}
- 运行结果:
Johnson-Trotter算法
- 思路:
对于任一一个包含n个不同元素的序列a1,a2,a3…an,通过不断地交换相邻的元素可以得到这个序列的全部排列。算法要用到两个辅助序列c1,c2,c3…cn(cj表示在aj的右侧小于aj的元素的数目,满足0<=cj<j)和o1,o2,o3…on(oj控制cj改变的方向)。
- 初始化:cj=0;oj=1,其中1<=j<=n;
- 访问序列a1,a2,a3…an。
- 令j=n,s=0.s表示排满足k>j且ck=k-1的ck的个数。
- 令q=cj+oj;如果q<j,执行步骤7;如果q=j,执行步骤6.
- 交换a[j-cj+s]和a[j-q+s],令cj=q,执行步骤2.
- 若j=1,结束算法;否则令s=s+1;
- 令oj=-oj,j=j-1,重复步骤4.
- 代码演示:
#include <iostream>
using namespace std;
const int MAXSIZE = 100;
int n;
int arr[MAXSIZE];
int c[MAXSIZE];
int o[MAXSIZE];
int change(int arr[], int i, int j)//交换数据3
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
return 0;
}
int print(int arr[], int n)//输出数组
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
int permutation(int arr[],int n)//排列
{
for (int i = 0; i < n; i++)//初始化c,o两个数组
{
c[i] = 0;
o[i] = 1;
}
int j = n - 1, s = 0;
print(arr, n);
while (true)
{
int q = c[j] + o[j];
if (q >= 0 && q != j + 1)
{
change(arr, j - c[j] + s, j - q + s);
print(arr, n);
c[j] = q;
j = n - 1;
s = 0;
continue;
}
if (q == j + 1)
{
if (j == 0)
break;
else
s++;
}
o[j] = -o[j];
j--;
}
return 0;
}
int main()
{
cout << "请输入n的值:";
cin >> n;
for (int i = 0; i < n; i++)
{
arr[i] = i + 1;
}
permutation(arr, n);
return 0;
}
运行结果如下: