字典序法生成排列

/**
    顾名思义,这种方法的思想就是将所有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)=(q1 q2 … qn);
(4)	(q)=(q1 q2 … qi-1 qi qi+1 … qn)中qi qi+1 … qn部分的顺序逆转,得新排列
    q1 q2 … qi-1 qn…qi+1 qi

    示例:
    当 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 <iostream>

using namespace std;

/*  函数功能:求出满足关系式P[k-1]<P[k]的k的最大值.
 *  输入参数:  p   in,指向n个字符的一个排列
 *             N   in,p所指缓冲区的长度
 *  返回值:上述描述所需的i值,-1表示调用参数有误
 */
int iMax(const char *p,const int N)
{
    if(p == NULL)
        return -1;
    int maxi = 0;
    for(int k=1;k<N;k++)
        if(p[k-1]<p[k])
        {
            maxi = k;
        }
    return maxi;
}

/*  函数功能:求出满足关系式P[i-1]<P[k]的k的最大值
 *  输入参数:  P   in,指向n个字符的一个排列
 *             i   in,关系式中的i值,由iMax函数求出
 *			   N   in,p所指缓冲区的长度
 *  返回值:上述描述所需的j值,-1表示调用参数有误
 */
int jMax(const char *p,const int i,const int N)
{
    if(p == NULL)
        return -1;
    int maxj = 0;
    for(int k=0;k < N;k++)
        if(p[i-1]<p[k])
            maxj = k;
    return maxj;
}

/*  函数功能,交换指针p1和p2所指的变量值
 */
bool swap(char *p1,char *p2)
{
    if( p1 == NULL || p2 == NULL)
        return false;
    char temp = *p1;
    *p1 = *p2;
    *p2 = temp;
    return true;
}

/*	函数功能:将ps和pe所指区间内容逆序
 */
bool reverse(char *ps,char *pe)
{
    if(ps == NULL || pe == NULL)
        return false;
    while(ps<pe)
    {
        swap(ps++,pe--);
    }
    return true;
}

int main()
{
	int N;
	cin >>N;
	char *array = new char[N+1];
	char *endArray = new char[N+1];
	for(int i=0;i<N;i++)
		array[i]=endArray[N-i-1]='1'+i;
	array[N]=endArray[N]='\0';
    int c=1;
    int i=0;
    int j=0;

    cout<<array;
    do{
        i = iMax(array,N);
        j = jMax(array,i,N);
        swap(array+i-1,array+j);
        reverse(array+i,array+N-1);
        cout<<"->"<<array;
		c++;
    }while(strcmp(array,endArray));
    cout<<endl;
	cout<<c<<endl;
	delete [] array;
	delete [] endArray;
    return 0;
}

运行结果:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值