您的位置:首页 > 编程语言 > Go语言

next_permutation 实现

2014-08-01 10:45 302 查看
之前实现的permutation一直是用数组(或者vector之类)的容器,然后递归出来的。面对要求快速求出next permutation的问题束手无策,今天看了STL中next_permution的实现,自己在没有看源码写一点吧。

#include <iostream>
#include <vector>
#include <string>

/* 算法的主要思想
以数组 0 1 2 4 3 为例
1. 从最末元素开始往前查找,找到第一对元素(第一个即为i,第二记为ii),
使*i < *ii,在本例为元素对 2 4
2. 从尾部开始往前查找,找出第一个大于i元素的值,记为j,此处为3
3. 然后交换i和j的元素,再将ii后的元素(含ii)逆置,即可得next permutaioin
例子的结果为 0 1 3 2 4
*/
template <typename T>
bool next_permutation (typename std::vector<T>::iterator first, typename std::vector<T>::iterator last)
{
typename std::vector<T>::iterator i, ii, j;

// 1. find the last pair of i and ii, let *i < *ii
ii = last - 1;
if (ii == first || first == last) // only 1 element or empty, done
return false;

i = ii - 1;
for (; *i > *ii; )
{
ii = i;
if (ii == first) // the next permutaion is not exist
return false;
-- i;
}
// found the pair

// 2. find the j
for (j = last - 1; j >= i && *j < *i; --j);

// 3. swap i and j
{
T tmp = *i;
*i = *j;
*j = tmp;
}

// reverse ii - j
while(j > ii)
{
T tmp = *j;
*j = *ii;
*ii = tmp;
-- j;
++ ii;
}

return true;
}

template <typename T>
void show(const typename std::vector<T> &v)
{
for (typename std::vector<int>::const_iterator i = v.begin(); i != v.end(); ++ i)
{
std::cout << *i << " ";
}
std::cout << std::endl;
}

int main()
{
int a[] = {0, 1, 2, 4, 3};
std::vector<int> va(a, a + sizeof(a) / sizeof(a[0]));
show<int>(va);

if (next_permutation<int>(va.begin(), va.end()))
{
show<int>(va);
}

int b[] = {4, 3, 2};
std::vector<int> vb(b, b + sizeof(b)/sizeof(b[0]));
show<int>(vb);

if (next_permutation<int>(vb.begin(), vb.end()))
{
show<int>(vb);
}
else
{
std::cout << "There is no next permutation!" << std::endl;
}

return 0;
}


SGI STL源码

// next_permutation and prev_permutation, with and without an explicitly
// supplied comparison function.

template <class _BidirectionalIter>
bool next_permutation(_BidirectionalIter __first, _BidirectionalIter __last) {
__STL_REQUIRES(_BidirectionalIter, _BidirectionalIterator);
__STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type,
_LessThanComparable);
if (__first == __last)
return false;
_BidirectionalIter __i = __first;
++__i;
if (__i == __last)
return false;
__i = __last;
--__i;

for(;;) {
_BidirectionalIter __ii = __i;
--__i;
if (*__i < *__ii) {
_BidirectionalIter __j = __last;
while (!(*__i < *--__j))
{}
iter_swap(__i, __j);
reverse(__ii, __last);
return true;
}
if (__i == __first) {
reverse(__first, __last);
return false;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  algorithm