生成全排列的字典序算法

字典序算法如下:
  设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=min{pk|pk>pj,k>i}
  3)对换pi,pk
  4)再将pj+1......pk-1pkpk+1pn倒转得到排列p’’=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。
  例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下:
  自右至左找出排列中第一个比右边数字小的数字4 839647521
  在该数字后的数字中找出比4大的数中最小的一个5 839647521
  将5与4交换 839657421
  将7421倒转 839651247
  所以839647521的下一个排列是839651247。
  我把自己写的源代码贴上来供大家学习:

#include<stdio.h>
#include<string.h>
int fact(int n);
void sort(char s[]);
void main()
{
int n,i;
char s[1000];
scanf("%d",&n);
for(i=0;i<n;i++)
s[i]=i+1+‘0‘;
s[i]=‘\0‘;
for(i=0;i<fact(n);i++)
{
printf("%s\n",s);
sort(s);//生成下一个排列数
}

}

int fact(int n)
{
int fact=1,i;
for(i=2;i<=n;i++)
fact=fact*i;
return fact;
}
void sort(char s[])
{
int len,i,j,tem,min;
len=strlen(s);
for(i=len-1;i>0;i--)
if(s[i-1]<s[i])
break;
min=i;
for(j=i+1;j<len;j++)
if(s[j]>s[i-1]&&s[j]<s[min])
min=j;
tem=s[i-1];
s[i-1]=s[min];
s[min]=tem;
for(j=i;j<(len+i)/2;j++)
{
tem=s[j];
s[j]=s[len-1+i-j];
s[len-1+i-j]=tem;
}
}

运行结果:

时间: 2024-10-08 09:03:56

生成全排列的字典序算法的相关文章

字典序法生成全排列算法的证明

引言 对一个给定数据进行全排列,在各种场合经常会用到.组合数学中,生成全排列的方法有很多,卢开澄老师的<组合数学>中就介绍了三种:序数法,字典序法,临位互换法等.其中以字典序法由于算法简单,并且使用的时候可以依照当前状态获取下一个状态,直到所有排列全部完成,方便在程序中随要随用,应用比较广泛,STL中的Next_permutation也是使用此法. 算法定义 首先看什么叫字典序,顾名思义就是按照字典的顺序(a-z, 1-9).以字典序为基础,我们可以得出任意两个数字串的大小.比如 "

Steinhaus-Johnson-Trotter 生成全排列算法

Steinhaus-Johnson-Trotter算法是一种基于最小变换的全排列生成算法,对于排列a[1...n],该算法通过将a[i],与a[i-1](或a[i+1])进行交换,生成下一个排列,直到所有排列生成完毕为止,这样,当前排列与其后继排列只是两个相邻位置的元素发生了调换.当然,为了防止重复生成某一个排列,算法并非随意调换某两个元素之间的位置,其生成全排列的具体规则如下. 首先,以字典序最小的排列起始,并且为该排列的每个元素赋予一个移动方向,初始所有元素的移动方向都向左. 在排列中查找这

寻找全排列的下一个数(字典序算法实现)

给出一个正整数,找出这个正整数所有数字全排列的下一个数.通俗的说就是在一个整数所包含数字的全部组合中,找到一个大于且仅大于原数的新整数.举例: 如果输入:12345,则返回12354 如果输入:12354,则返回12435 如果输入:12435,则返回12453 思路: 字典序算法: 从后向前查看逆序区,找到逆序区域的前一位,作为数字置换的边界: 逆序区是指:数字大小(从左到右)排序一定会是从大到小. 所以从右往左找,第一个右边值大于左边值的位置,那么右边这个位置就是逆序区的起始点. 从右向左,

全排列与字典序排列

首先,全排列是一个比较简单的问题,但我却没有真正的去实现过全排列. 让我独自思考全排列的话,如将 " abcd" 进行全排列,这种简单的全排列也能将我难住,因为真的没有考虑过这种问题.思考了一会,我只能给出以下比较麻烦的算法: //字符串全排列 void printRE(char* str,int index,char s[],int length){ if(index == length) printf("%s \n",str); else{ bool exsis

[LeetCode] “全排列”问题系列(一) - 用交换元素法生成全排列及其应用,例题: Permutations I 和 II, N-Queens I 和 II,数独问题

转:http://www.cnblogs.com/felixfang/p/3705754.html 一.开篇 Permutation,排列问题.这篇博文以几道LeetCode的题目和引用剑指offer上的一道例题入手,小谈一下这种类型题目的解法. 二.上手 最典型的permutation题目是这样的: Given a collection of numbers, return all possible permutations. For example,[1,2,3] have the foll

随机生成32位字符串算法

随机生成32位字符串算法: function getRandom() { var arr = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D"

字典序法生成全排列算法图

算法定义 首先看什么叫字典序,顾名思义就是按照字典的顺序(a-z, 1-9).以字典序为基础,我们可以得出任意两个数字串的大小.比如 "1" < "12"<"13". 就是按每个数字位逐个比较的结果.对于一个数字串,"123456789", 可以知道最小的串是 从小到大的有序串"123456789",而最大的串是从大到小的有序串"*987654321".这样对于"1

不存数据库生成验证码(totp算法)

以前做验证式的方法都是new Random().Next(10000,99999) 生成随机数了以后存到数据库中的用户表中,用户输入验证码了再查询用户表做比较的,网友说这种做法太LOW B了,应该用TOTP算法来弄,同时给了一个网址过来,https://github.com/Arch/Standard/blob/master/src/Arch.Standard/Utils/Totp.cs 上去看了下,不太懂,不过应该还是会用的,自己试了一下,可以用,不错不错,支持支持... 代码已加入自己的牛腩

字符串全排列和组合算法

打印字符串的全排列 算法的思路: 把一个字符串分成两部分,第一个字符+后面部分所有的字符.这样就能够递归的求解整个过程了: 1.每个字符都做一次首字符 2.当某个字符作为首字符的时候,求后面所有字符的全排列 而这里的求后面所有字符的全排列可以看成递归的子问题 全排列的递归树: 但是这里还有一个问题,那就是字符串中有重复的字符时,这样的算法会增加最后的结果数目.比如说字符串aab,a+ab的全排列,然后交换还是a+ab的全排列.所以会增加结果的数目.解决方案就是:当遇到重复的字符的时候就跳过去,不