STL:next_permutation算法
什么是全排列呢?
全排列是从N个元素中取出M个元素,并按照一定的规则将取出元素排序,我们称之为从N个元素中取出M个元素的一个排列,当M=N时,即从N个元素中取出N个元素的排列。
比如:A={a,b,c};
这个序列的全排列为:
A1={a,b,c}, A2={a,c,b}, A3={b,a,c}, A4={b,c,a}, A5={c,a,b}, A6={c,b,a}
1.概念概述:
C++的STL容器中提供了两种全排列算法,用于指定序列生成不同的排列:
1.1“下一个”排列组合
next_permutation(begin,end);
按照变量顺序生成给定序列的下一个较大序列,比如给定“abc”,那么next_permutation(begin,end)就会生成下一个较大的序列“acb”。
bool next_permutation(begin,end);标示下一个排列组合,如果没有下一个排列组合,就返回false,否则执行完相关算法之后返回true。
1.2"前一个"排列组合
prev_permutation(begin,end);
与next_permutation(begin,end)原理相同,顺序相反。
2.算法原理:
这里以bool next_permutation(begin,end)为例说明其原理,bool next_permutation(begin,end);原理相同,顺序反之。
①从这个序列的最后一个位置开始寻找两个相邻的元素,在这两个元素中,前一个元素(记为i)<后一个元素(记为j)。
②再从这个序列的末尾找到第一个比i大的元素(记为t),然后交换i和t的位置。
③将j(包括j在内)之后的元素进行逆置。
这是一轮下来的思路原理。
如下图:
第一轮:
第二轮:
后面依次类推。
3.代码实现:
//自己定义
template<class T>
bool nextpermutation(T first, T last)
{
//空区间
if (first == last)
{
return false;
}
T i = first;
i++;
//只有一个元素
if (i == last)
{
return false;
}
//i指向尾端
i = last;
--i;
while (1)//死循环
{
T j = i;//倒数第一个
--i;//倒数第二个
if (*i < *j)//前一个元素小于后一个元素
{
//从尾部开始寻找第一个比i大的元素,进行交换
T t = last-1;
while (*i >= *t)
{
--t;
}
//交换i,t
iter_swap(i, t);
//j以及j之后的元素进行逆转
reverse(j, last);
return true;
}
//已经到第一个了
if (i == first)
{
reverse(i, last);
return false;
}
}
}