排列的生成算法之字典序法

顾名思义,这种方法的思想就是将所有n元排列按“字典顺序”排成队,以12...n为第一个排列,排列的规则,也就是由一个排列(p)={p1p2...pn}直接生成下一个排列的算法

可归结为:

(1)求满足关系式p(k-1) < p(k) 的k的最大值,设为i,即 i = max{k | p(k-1) < p(k)}

(2)求满足关系式p(i-1) <  p(k) 的k的最大值,设为j,即 j = max{k | p(i-1) < p(k)}

(3)p(i-1)与p(j)互换位置得    (q) = (q1q2...qn)

(4)(q) = (q1q2...qi-1qiqi+1...qn)中 qiqi+1...qn部分的顺序逆转,得  q1q2...qi-1qn...qi+1qi  这便是所求的下一个排列。

例如,设p1p2p3p4=1234, 那么, i=2, j=2, p1与p2交换得 q1q2q3q4=4321, 再将321逆转即得下一个排列4123.

当n=4时, 由字典法所得的全部排列的先后顺序如下:

  1234->1243->1324->1342->1423->1432->2134->2143->2314->2341->2413->2431->

  3124->3142->3214->3241->3412->3421->4123->4132->4213->4231->4312->4321


程序实现如下:

#include <stdio.h>
#include <stdlib.h>
#define N 4
int dictionary(int a[], int n)
{
int i = 0, j = 0;
int k = 0, h = 0;
int temp = 0;
k = 0;
for (i = 2; i < n; i++)  //k = max{i | a[i-1] < a[i]}
{
if (a[i-1] < a[i])
{
k = i;
}
}
if (k == 0)
{
return 0;
}
h = 0;
for (i = k; i < n; i++)  //h = max{i | a[k-1] < a[i]}
{
if (a[k-1] < a[i])
{
h = i;
}
}
temp = a[k-1];          //a[k-1]与a[h]交换位置
a[k-1] = a[h];
a[h] = temp;
for (i = k, j = n-1; i < j; i++, j--)  //部分序列逆转
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
for (i = 1; i < n; i++)   //输出所求序列
{
printf("%d", a[i]);
}
printf("    ");
dictionary(a, n);   //求下一个排列
return 0;
}
int main (void)
{
int a[N+1];
int i = 0;
printf("所求序列为:\n");
for (i = 1; i <= N; i++)
{
a[i] = i;
printf("%d",a[i]);
}
    printf("    ");
dictionary(a, N+1);
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值