字典序全排列算法研究
一. 非递归算法(字典序法)
对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是从左到右逐个比较对应的字符的先后。
例如:字符集{1,2,3},较小的数字位置较先,这样按字典序生成的全排列是
123,132,213,231,312,321
※ 一个全排列可看做一个字符串,字符串可有前缀、后缀。
生成给定全排列的下一个排列.所谓一个的下一个就是这一个与下一个之间没有其他的。这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。
对于按字典的顺序给出的排列,由一个排列生成下一个排列的算法如下:
【例】 一般而言,设P是[1,n]的一个全排列。
P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn
find: j=max{i|Pi<Pi+1}
k=max{i|Pi>Pj}
1, 对换Pj,Pk,
2, 将Pj+1…Pk-1PjPk+1…Pn翻转
P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一个
【例】 如何得到346987521的下一个
1,从尾部往前找第一个P(i-1) < P(i)的位置
3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1
最终找到6是第一个变小的数字,记录下6的位置i-1
2,从i位置往后找到最后一个大于6的数
3 4 6 -> 9 -> 8 -> 7 5 2 1
最终找到7的位置,记录位置为m
3,交换位置i-1和m的值
3 4 7 9 8 6 5 2 1
4,倒序i位置后的所有数据
3 4 7 1 2 5 6 8 9
则347125689为346987521的下一个排列
代码:用C++实现将以下国家按字典序排列
#include<stdio.h> #include<string.h> int main() { char str[8][9]={"CHINA","JAPAN","KOREA","INDIA","CANADA","AMERICAN","ENGLAND","FRANCE"}; char temp[9]; int i,l; for (i=0;i<8;i++){ for(l=0;l<9;l++){ printf("%c",str[i][l]); } printf("\n"); } //排序 printf("以上8个国家按字典中排序如下所示:\n"); int j,k; for(j=0;j<8;j++) for(k=j+1;k<8;k++) { if(strcmp(str[j],str[k])>0) {//交换 strcpy(temp,str[j]); strcpy(str[j],str[k]); strcpy(str[k],temp); } } for(i=0;i<8;i++)//输出 printf("%s\n",str[i]); }
【算法】:排列的字典序问题
Time Limit:2000MS Memory Limit:65536K
Total Submit:69 Accepted:13
Description
n个元素{1,2,..., n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下:
任务:给定n 以及n 个元素{1,2,..., n }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。
Input
第1 行是元素个数n(n < 15)。接下来的1 行是n个元素{1,2,..., n }的一个排列。
Output
第一行是字典序值,第2行是按字典序排列的下一个排列。
Sample Input
8
2 6 4 5 8 1 7 3
Sample Output
8227
2 6 4 5 8 3 1 7
代码后补!
全排序之字典排序