java 全排列非递归算法_全排列算法的c++实现(非递归)

本文算法出自:梦辽软件,只实现了文中所说的第五种算法/*

全排列(非递归求顺序)算法

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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值