STL next_permutation与prev_mutation解析
来源:互联网 发布:亚拉腊山 知乎 编辑:程序博客网 时间:2024/06/05 03:29
这两个函数主要实现的功能是排列组合方面的操作,以前对于序列的全排列算法递归的、非递归的都看过几个,最近看《STL源码剖析》,感觉SGI STL里面的实现也颇为巧妙。
首先说下next_permutation,该函数求当前序列的下一个组合,算法很巧妙,具体思想是:从最尾端开始寻找两个相邻的元素,令第一个元素是i,第二个元素是ii,且*i < *ii,找到这样一组元素后,再从尾端开始往前选择第一个大于*i的元素,将i、j元素对调,然后将ii之后的所有元素逆序排列,就得到了下一个组合。源码如下:
算法的原理很简单,但是关键问题是为什么这样可以得到当前序列的下一个组合?
首先从后往前寻找一个数对,且第一个元素小于第二个元素,这个很好理解,因为全排列就是把数列从完全顺序排序一步步转换到完全的逆序,这是目前从后往前第一个顺序的数对,所以肯定在此处下手。关键是为何把i与从后往前第一个大于它的元素交换,并且颠倒[i+1, last)的元素就可以得到下个组合?根据算法思想可以肯定的是[first, i)这部分元素与原来的序列肯定相同,把i与从后往前第一个大于它的元素j替换,则不管后面如何排列,由于*j > *i,得到的新排列肯定大于原来的排列,下面需要说明的就是如何保证这个新排列是原来排列的下一个,而不是下一个的下一个或者…。
i和ii是从后往前第一个顺序的数对,这就可以肯定[ii, last)这部分区域肯定是逆序的,所以*(j-1) > *j并且*j > *(j+1),而*j是从后往前第一个大于*i的元素,故*(j-1)>*j >*i > *(j+1),所以*i与*j置换后[ii, last)这部分数据仍然是逆序的,既然如此,我们把这部分数据reverse一下,就得到了完全顺序的序列,在排列组合中,这是最小的情况,因此可以肯定得到的新的排列是原序列的下一个组合。
理解了next_permutation的原理后,再来看prev_permutation就简单多了。Prev_mutation的思想是:从后往前寻早第一个逆序的数对,第一个元素为*i,第二个元素为*ii,且*i > *ii,再从后往前寻找第一个小于*i的元素*j,将i、j对调,然后将ii之后的元素颠倒就得到了前一个组合。源码如下:
prev_mutation和next_mutation的思想很相似,这里简单说下。[ii, last)直接的元素是顺序排列的,因为i和ii是第一个逆序的数对,*j是从后往前第一个小于*i的元素,可以肯定*j是ii后小于*i的最大的元素,i、j置换,i之前的元素没变,而*j < *i,这样就保证新序列小于原序列,同时由于*(j-1) < *j < *i < *(j+1),故置换后,ii之后的序列仍然是顺序排列的,把这部分数据reverse,就得到了这部分数据组合的最大情况,故是原序列的上一个排列。
[参考侯捷先生著作《STL源码剖析》]
- STL next_permutation与prev_mutation解析
- STL的next_permutation与prev_permutation解析
- STL排序next_permutation算法解析
- STL next_permutation
- 【STL】next_permutation
- [STL]next_permutation
- c++ stl下一个组合 next_permutation() 简单解析
- C++ STL之next_permutation小证明与Java实现
- 全排列递归算法与STL:next_permutation()函数
- 【C++ STL应用与实现】62: 如何使用std::next_permutation
- stl全排列next_permutation()与prev_permutation()函数用法
- STL快速全排列函数next_permutation与pre_permutation
- stl算法:next_permutation剖析
- POJ1061(STL next_permutation)
- stl算法:next_permutation剖析
- STL next_permutation 全排列
- stl算法:next_permutation剖析 .
- STL prev_permutation&next_permutation
- mac卸载xcode
- 心死。。
- 学习资料网址
- SQL 查询四舍五入解决方案
- 面向接口编程详解(一)——思想基础
- STL next_permutation与prev_mutation解析
- HDU 2896 病毒侵袭 (AC自动机)
- Java 接口大全、面向接口编程
- fscanf用法
- 柳传志的人才管理学
- 掌握Oracle中"Kill"进程的方法
- GridView 几种使用方法(转)
- 上載EXCEL以及ALV顯示例子
- 关于Microsoft Office Document ImageWriter