字典序全排列算法

一、非递归方法(字典序法)

这种算法用在C++的STL库中
对给定的字符集中的字符规定了一个先后顺序,在此基础上规定两个全排列的先后是从左到右逐个比较字符的先后顺序
[例]字符集{ 1 , 2 , 3 },较小的数字较先,这样按字典序生成的全排列是: 123 , 132 , 213 , 231 , 312 , 321
※ 一个全排列可看做一个字符串,字符串可有 前缀 后缀
  生成给定全排列的下一个排列.所谓 一个的下一个 就是这一个与下一个之间 没有其他的 。这就要求这一个与下一个有尽可能 共同前缀 ,也即变化限制在尽可能 后缀 上。

[例]839647521是1--9的排列。 1 —9的排列最前面的是123456789,最后面的987654321,从右向左扫描若都是增的,就到了987654321,也就没有下一个了。否则找出第一次出现下降的位置。


【例】 如何得到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的下一个排列

代码:
private static void PermutationList() { int fromIndex, endIndex, changeIndex; Sort( 0 , length - 1 ); do { // 输出一种全排列 Output(); fromIndex = endIndex = length - 1 ; // 向前查找第一个变小的元素 while (fromIndex > 0 && words[fromIndex] < words[fromIndex - 1 ]) -- fromIndex; changeIndex = fromIndex; if (fromIndex == 0 ) break ; // 向后查找最后一个大于words[fromIndex-1]的元素 while (changeIndex + 1 < length && words[changeIndex + 1 ] > words[fromIndex - 1 ]) ++ changeIndex; Swap(fromIndex - 1 , changeIndex); // 交换两个值 InvertArray(fromIndex, endIndex); // 对后面的所有值进行反向处理 } while ( true ); }

递归方法求全排列
递归方法很容易理解:分别将每个位置交换到最前面位,之后全排列剩下的位。

/// <summary> /// 递归方式生成全排列的方法 /// </summary> /// <param name="fromIndex"> 全排列的起始位置 </param> /// <param name="endIndex"> 全排列的终止位置 </param> private static void PermutationList( int fromIndex, int endIndex) { if (fromIndex == endIndex) Output(); else { for ( int index = fromIndex; index <= endIndex; ++ index) { // 此处排序主要是为了生成字典序全排列,否则递归会打乱字典序 Sort(fromIndex, endIndex); Swap(fromIndex, index); PermutationList(fromIndex + 1 , endIndex); Swap(fromIndex, index); } } }


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值