本文算法出自:梦辽软件,只实现了文中所说的第五种算法/*
全排列(非递归求顺序)算法
1、建立位置数组,即对位置进行排列,排列成功后转换为元素的排列;
2、按如下算法求全排列:
设P是1~n(位置编号)的一个全排列:p = p1,p2...pn = p1,p2...pj-1,pj,pj+1...pk-1,pk,pk+1...pn
(1)从排列的尾部开始,找出第一个比右边位置编号小的索引j(j从首部开始计算),即j = max{i | pi
(2)在pj的右边的位置编号中,找出所有比pj大的位置编号中最小的位置编号的索引k,即 k = max{i | pi > pj}
pj右边的位置编号是从右至左递增的,因此k是所有大于pj的位置编号中索引最大的
(3)交换pj与pk
(4)再将pj+1...pk-1,pk,pk+1...pn翻转得到排列p' = p1,p2...pj-1,pj,pn...pk+1,pk,pk-1...pj+1
(5)p'便是排列p的下一个排列
例如:
24310是位置编号0~4的一个排列,求它下一个排列的步骤如下:
(1)从右至左找出排列中第一个比右边数字小的数字2;
(2)在该数字后的数字中找出比2大的数中最小的一个3;
(3)将2与3交换得到34210;
(4)将原来2(当前3)后面的所有数字翻转,即翻转4210,得30124;
(5)求得24310的下一个排列为30124。
*/
#include
using namespace std;
template
void print(T* arr,int len) {
int i = 0;
while(i
{
cout<
i++;
}
cout<
}
template
void swap(T* arr,int i,int j) {
T t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
template
bool sort(T* arr,int len) {
int j;
for (j = len - 2; j >= 0 && arr[j] > arr[j + 1]; j--)
//本循环从位置数组的末尾开始,找到第一个左边小于右边的数的位置,即j
;
if (j
return false; //已完成全部排列
T tmp = arr[j];
int index = -1,k;
for (k = len - 1; k > j; k--)
//即找出索引j右边的数中所有大于arr[j]元素中的最小元素的索引
{
if(tmp != arr[j] && arr[k] > arr[j] && arr[k]
{
tmp = arr[k];
index = k;
}
else if(tmp == arr[j] && arr[k] > tmp)
{
tmp = arr[k];
index = k;
}
}
swap(arr, j, index);
for (j = j + 1, k = len - 1; j
//本循环翻转j+1到末尾的所有位置
swap(arr, j, k);
return true;
}
int main(int argc,char* argv[])
{
int times = 0;
char elem[] = {'z','q','f','t','2'};//要进行全排列的元素
int index[5] = {0,1,2,3,4};//元素的索引,0对应'z',.....,4对应'2'
do {
char tmp[5];
int i = 0;
while(i
{
tmp[i] = elem[index[i]];
i++;
}
print(tmp,5);
print(index,5);
times++;
} while (sort(index,5));
cout<
return 0;
}