打印全排列和stl::next_permutation
打印全排列是个有点挑战的编程问题。STL提供了stl::next_permutation完美的攻克了这个问题。
可是,假设不看stl::next_permutation,尝试自己解决,怎么做?
非常自然地,使用递归的办法:
1. 单个元素的排列仅仅有1个。
2. 多个元素的排列能够转化为:
以每一个元素为排列的首个元素,加上其它元素的排列。
有了思路,就能够编码了。
第一个版本号:
prefix, int set[], int n)
i<n; ++i)
= set[i];
== 1)
" ;
shift set[0,i) to right by 1
j>=0; --j)
shift set[0,i) to left by 1
j<i; ++j)
測试:
myints, 4);
通过。
这样的方法的缺点是产生了大量的string对象。
怎么避免呢?
第二个版本号:
i<n; ++i)
= set[i];
== n-1)
it is possible use callback here instead of printing a permutation
j<n; ++j)
' ;
shift set[from,i) to right by 1
j>=from; --j)
shift set[from,i) to left by 1
j<i; ++j)
測试:
通过。
第二个版本号相比第一个版本号的还有一个改进是能够非常easy地改变成回调函数的形式,扩展函数的用途。而不不过打印排列。
似乎非常不错了。
可是和stl::next_permutation相比,以上的方案就太逊了。
1. stl::next_permutation支持部分排列,而不必是全排列。你能够从不论什么一个排列開始,能够随时退出next_permutation循环。
2. stl::next_permutation支持多重集的排列。比如:
= {1,2,2,2};
' << myints[1] << ' ' <<
myints[2] << ' ' << myints[3]
<< '\n';
std::next_permutation(myints,myints+4) );
输出:
1 2 2 2
2 1 2 2
2 2 1 2
2 2 2 1
没有反复的排列。
stl::next_permutation这么强大,非常值得看看它到底是怎么实现的。
_First, _BidIt _Last)
and test for pure ascending, using operator<
== _Last || _First == --_Next)
; )
find rightmost element smaller than successor
*_Next1))
swap with rightmost element that's smaller, flip suffix
!_DEBUG_LT(*_Next, *--_Mid); )
== _First)
pure descending, flip all
_First, _BidIt _Last)
and test for pure ascending, using operator<
_CHECKED_BASE(_Last));
代码不长,但须要研究才干理解。
非常多算法都是这种。
这个算法能够概括为:
假设仅仅有零个或一个元素,返回false,表示回到全排列的起点。
否则。从右边開始。找到第一个不是递减的元素,即E(i) < E(i+1),从E(i+1)一直到E(n)都是不增的。
假设找到。从右边開始。找到大于E(i)的那个元素E(x)【一定会找到】,交换E(i)和E(x),然后把E[i+1, n]范围内的元素反转。
返回true。
假设找不到,把整个范围内的元素反转,返回false,表示回到全排列的起点。
为什么这个算法可行呢?看以下1 2 3 4的全排列。
能够非常easy地看到,
假设把每一个排列看成一个数,那么下一个排列大于上一个排列。
由上可知,第一个排列是最小排列【不减排列】。最后一个排列是最大排列【不增排列】。
最小排列和最大排列是反序的关系。
算法的关键:从E(i+1)一直到E(n)都是不增的。
这个特性说明,这一范围的元素的排列是一个最大排列,下一个排列必然是找到这一范围内大于这一范围的前一元素的元素,交换这两个元素,交换后E[i+1, n]仍为不增排列【最大排列】。反转之后,变成最小排列。这样处理后得到的排列正好是E[0,n]的下一个排列。
1 2 3 4
1 2 4 3
1 3 2 4
1 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 1 3
2 4 3 1
3 1 2 4
3 1 4 2
3 2 1 4
3 2 4 1
3 4 1 2
3 4 2 1
4 1 2 3
4 1 3 2
4 2 1 3
4 2 3 1
4 3 1 2
4 3 2 1
打印全排列和stl::next_permutation的更多相关文章
- STL - next_permutation 全排列函数
学习: http://blog.sina.com.cn/s/blog_9f7ea4390101101u.html http://blog.csdn.net/ac_gibson/article/deta ...
- STL next_permutation(a,a+n) 生成一个序列的全排列。满足可重集。
/** 题目: 链接: 题意: 思路: */ #include <iostream> #include <cstdio> #include <vector> #in ...
- STL next_permutation 全排列
调用方法: ]={,,,}; )){ ;i<;i++) printf("%d ",arr[i]); puts(""); } 测试效果: 注:可以看到1 2 ...
- STL next_permutation和prev_permutation函数
利用next_permutation实现全排列升序输出,从尾到头找到第一个可以交换的位置, 直接求到第一个不按升序排列的序列. #include <iostream> #include & ...
- STL next_permutation 算法原理和自行实现
目标 STL中的next_permutation 函数和 prev_permutation 两个函数提供了对于一个特定排列P,求出其后一个排列P+1和前一个排列P-1的功能. 这里我们以next_pe ...
- STL next_permutation 算法原理和实现
转载自:https://www.cnblogs.com/luruiyuan/p/5914909.html 目标 STL中的next_permutation 函数和 prev_permutation 两 ...
- C++ 全排列函数 std::next_permutation与std::prev_permutation
C++ STL中提供了std::next_permutation与std::prev_permutation可以获取数字或者是字符的全排列,其中std::next_permutation提供升序.st ...
- 全排列(STL)
输入一个整数n,输出1~n的全排列(是不是很水) 在此记录stl做法 #include<bits/stdc++.h> using namespace std; ]; int main(){ ...
- C++中全排列算法函数next_permutation的使用方法
首先,先看对next_permutation函数的解释: http://www.cplusplus.com/reference/algorithm/next_permutation/?kw=next_ ...
随机推荐
- spring batch(二):核心部分(1):配置Spring batch
spring batch(二):核心部分(1):配置Spring batch 博客分类: Spring 经验 java chapter 3.Batch configuration 1.spring ...
- hive1.2伪分布mysql数据库配置具体解释
hadoop2.6伪分布配置:http://blog.csdn.net/gamer_gyt/article/details/46793731 hive1.2 derby元数据库配置:http://b ...
- Linux less命令简介
less命令可以对文件或其它输出进行分页显示,与moe命令相似,但是比more命令要强大许多. 在 less 中导航命令类似于 vi,如下: 1 搜索 当使用命令 less file-name 打开一 ...
- log4j日志存储到数据库
一.前提条件 系统必须是使用LOG4J进行日志管理,否则方法无效. 系统必须包含commons-logging-xxx.jar,log4j-xxx.jar这两个JAR包,XXX为版本号. 二.操作步骤 ...
- C#对 Json的序列化和反序列化时出现“k_BackingField”
在C#2.0的项目中,以前经常使用Json.NET实现序列化和反序列化.后来从c#3.0中开始使用新增的DataContractJsonSerializer进行json相关的操作.微软提供的原生类库使 ...
- WPF MVVM 从Prism中学习设计模式之Event Aggregator 模式
Prism简介 Prism是由微软Patterns & Practices团队开发的项目,目的在于帮助开发人员构建松散耦合的.更灵活.更易于维护并且更易于测试的WPF应用或是Silverlig ...
- SQLSERVER 链接服务器执行存储过程
1.创建链接服务器 exec sp_addlinkedserver 'server_tmp','','SQLOLEDB','192.168.1.1' -- server_tmp 为别名 exec sp ...
- child和childNodes的区别
child和childNodes区别: childNodes是标准属性, child是非标准属性 childNodes: 获取节点,不同浏览器表现不同 IE 只获取元素节点 非IE 获取元素节点和文本 ...
- (转)硬盘结构,主引导记录MBR,硬盘分区表DPT,主分区、扩展分区和逻辑分区,电脑启动过程
硬盘结构硬盘有很多盘片组成,每个盘片的每个面都有一个读写磁头.如果有N个盘片.就有2N个面,对应2N个磁头(Heads),从0.1.2开始编号.每个盘片的半径均为固定值R的同心圆再逻辑上形成了一个以电 ...
- 其他信息: 具有固定名称“Npgsql”的 ADO.NET 提供程序未在计算机或应用程序配置文件中注册或无法加载。有关详细信息,请参阅内部异常
其他信息: 具有固定名称“Npgsql”的 ADO.NET 提供程序未在计算机或应用程序配置文件中注册或无法加载.有关详细信息,请参阅内部异常 解决方法 在 App.config 的 configur ...