全排列生成的算法分析


字典序法

      字典序法中,对于数组1, 2, 3.....n的排列, 不同排列的先后顺序是从左到右逐个比较对应的数字的先后来决定的。例如,对于5个数字的排列12354和12345,排列12345在前,12354在后, 按照这样的规定,5个数字中排列在最前面的是12345, 排在最后面的事54321。

 

字典序算法思想如下:

     设P是1~n的一个全排列, p = p1p2......pn = p1p2.....pj-1pjpj+1.....pk-1pkpk+1....pn。

     (1)从排列的右端开始, 找出第一个比右边数字小的数字序号j ( j从左端开始计算), 即 j = max{ i | pi < pi+1 }。

     (2)在 pj 右边的数字中,找出所有比 pj 大的数中最小的数 pk , 即 k = max{ i | pi > pj }   (右边的数从右自左是递增的,因此 k 是所有大于 pj 的数字中序号最大者)

       (3)   对换 pi , pk 。

       (4)   再将 pj+1.....pk-1pkpk+1...pn 倒转得到排列 pn = p1p2.....pj-1pjpn....pk+1pkpk-1....pj+1 , 这就是排列 p 的下一个排列。

例如:

     839647521 是数字 1~9 的一个排列。

     从它生成下一个排列的步骤如下:

     (1)自右至左找出排列中第一个比右边小的数字4                 8396 4 7521

     (2)在该数字后的数字中找出比4大的数中最小的一个数5    8396 4 7 5 21

     (3)将 5 与 4 交换                                                                            8396 5 74 21

     (4)再将 7421 倒转                                                                          8396 5 12 4 7

      这样就获得了839647521的下一个排列   83965124 7

 

 

 源代码如下

#include<iostream>
#include<algorithm>
using namespace std;

void dict(int p[], int n);
void outp(int p[], int n);

int main()
{
	int length;
	cin>>length;
	int p[9] = {
		0, 1, 2, 3, 4, 5, 6, 7, 8
	};
	dict(p, length);
	return 0;
} 

void dict(int p[], int n)
{
	int i, j;
	outp(p, n);
	i = n - 1;
	while(i > 0)
	{
		if(p[i] < p[i+1])
		{
			for(j = n; j >= i+1; j--)
			{
				if(p[i] <= p[j])
				{
			         break;
				}
			}
			swap(p[i], p[j]);
			for(j = n; j >= 1; j--)
			{
				i += 1;
				if(i >= j) break;
				swap(p[i], p[j]);
			}
			outp(p, n);
			i = n;
		}
		i -= 1;
	}
}

void outp(int p[], int n)
{
	int i;
	for(i = 1; i <= n; i++)
	{
		cout<<p[i]<<" ";
	}
	cout<<endl;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值