全排列顾名思义指的是给定一个序列找出其所有的排列方式,例如给定字符串"abc",全排列为:abc、acb、bac、bca、cab、cba。对于不包含相同字符的字符串而言共有n!个排列方式。
解法一、字典序排列算法(非递归)
在字典序排列算法中,排列出现的不同次序是按照从右到左对字符的比较而确定的。例如,我们要对1、2、3、4进行全排列,第一个排列为1234,最后一个排列为4321,也就是说后一个排列要大于前一个排列,那么3142的下一个排列必为3214,这个3214是如何得来的呢?现在我们来看看字典序排列算法的基本思想:
给定已知序列A=P1 P2 P3 P4......Pn(其中1、2、3、4...n为下标)
<1>对输入序列进行升序排列
<2>从序列的右端开始,向左寻找相邻两个字符中第一个比右端小的字符,下标记为i。
<3>在Pi的右边寻找比Pi大的所有字符中最小的一个字符,下标记为j,交换Pi与Pj的值,然后颠倒i右边字符
<4>重复步骤<2>和<3>
例如数字698752431是1~9的一个全排列 ,那么它的下一个排列的计算如下:
我们发现从右端开始,相邻字符中第一个比右端小的字符为2(2 < 4) 698752431
在2的右边所有比2大的字符中最小的一个为3, 698752431
交换2和3的位置 698753421
对3右边的字符进行颠倒 698753124
代码如下:
#include <iostream>
using namespace std;
void permutation(int array[], int n);
bool has_next(int array[], int n);
void print_permutation(int array[], int n);
void quick_sort(int array[],int start,int end);
int partion(int array[], int start, int end);
void reserve(int array[], int satrt, int end);
int main()
{
int array[5] = { 1, 3, 5, 7};
permutation(array, 4);
}
void permutation(int array[],int n)
{
/*对输入字符进行升序排序:快速排序*/
quick_sort(array, 0, n - 1);
print_permutation(array, n);
while (has_next(array, n))
print_permutation(array, n);
}
/*
*/
bool has_next(int array[],int n)
{
/*寻找相邻两个元素中第一个比右端小的元素*/
int i;
for (i = n - 2; i >= 0;i--)
{
if (array[i] < array[i+1])
break;
}
if (i < 0)//没有下一个元素
return false;
/*寻找array[i]右端比array[i]大的所有元素中最小的元素*/
int j = i+1,k;
for (k = i + 2; k < n;k++)
{
if (array[k] > array[i] && array[k] < array[j])
j = k;
}
/*交换array[i]与array[j]的位置*/
int tmp;
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
/*颠倒array[i]右端的元素*/
reserve(array, i + 1, n-1);
return true;
}
void print_permutation(int array[], int n)
{
for (int i = 0; i < n; i++)
cout << array[i];
cout << endl;
}
void quick_sort(int array[], int start, int end)
{
if (start < end)
{
int p = partion(array,start,end);
quick_sort(array, start, p - 1);
quick_sort(array, p + 1, end);
}
}
int partion(int array[], int start, int end)
{
int key = array[end];
int i, j;
j = 0;
int tmp;
for (i = 0; i < end;i++)
{
if (array[i] < key)
{
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
j++;
}
}
array[end] = array[j];
array[j] = key;
return j;
}
void reserve(int array[], int satrt, int end)
{
int tmp;
while (satrt < end)
{
tmp = array[satrt];
array[satrt] = array[end];
array[end] = tmp;
satrt++;
end--;
}
}
运行结果: