Вдруг кому пригодится :)
Делал максимально обобщенно, в духе STL, проверял на Open Watcom C++.
(с)
Код:
template< typename Bidirectional, typename Compare >
bool prev_kpermutation( Bidirectional first, Bidirectional middle,
Bidirectional last, Compare comp )
{
typedef typename std::iterator_traits< Bidirectional >::difference_type Int;
if( first == last ) return false;
Int n = std::distance(first, last);
Int k = std::distance(first, middle);
if ((k > n) || (k <= 0)) return false;
Bidirectional i = last;
for(Bidirectional j = middle; j-- != first; )
{
if (std::min_element(j,last,comp) != j) { i = j; break; }
}
if (i == last) return false;
Bidirectional j = i;
++j;
while(!comp(*j,*i)) ++j;
Bidirectional imin = j;
for(; j != last; ++j)
{
if (comp(*j,*i) &&
comp(*imin,*j))
{
imin = j;
}
}
std::swap( *i, *imin );
++i;
Bidirectional u = first;
std::advance(u,std::min(k,n-1));
while ( i != u )
{
Bidirectional imin = i;
for(Bidirectional j = i; ++j != last;)
{
if (comp(*imin,*j)) imin = j;
}
std::swap( *imin,*i );
++i;
}
return true;
}
template< typename Bidirectional >
bool prev_kpermutation( Bidirectional first, Bidirectional middle, Bidirectional last )
{
return ( prev_kpermutation( first, middle, last,
std::less< typename std::iterator_traits< Bidirectional >::value_type >( )
) );
}
template< typename Bidirectional, typename Compare >
bool next_kpermutation( Bidirectional first, Bidirectional middle,
Bidirectional last, Compare comp )
{
typedef typename std::iterator_traits< Bidirectional >::difference_type Int;
if( first == last ) return false;
Int n = std::distance(first, last);
Int k = std::distance(first, middle);
if ((k > n) || (k <= 0)) return false;
Bidirectional i = last;
for(Bidirectional j = middle; j-- != first; )
if (std::max_element(j,last,comp) != j) { i = j; break; }
if (i == last) return false;
Bidirectional j = i;
++j;
while(!comp(*i,*j)) ++j;
Bidirectional imin = j;
for(; j != last; ++j)
{
if (comp(*i,*j) &&
comp(*j,*imin))
{
imin = j;
}
}
std::swap( *i, *imin );
++i;
Bidirectional u = first;
std::advance(u,std::min(k,n-1));
while ( i != u )
{
Bidirectional imin = i;
for(Bidirectional j = i; ++j != last;)
{
if (comp(*j,*imin)) imin = j;
}
std::swap( *i, *imin );
++i;
}
return true;
}
template< typename Bidirectional >
bool next_kpermutation( Bidirectional first, Bidirectional middle, Bidirectional last )
{
return ( next_kpermutation( first, middle, last,
std::less< typename std::iterator_traits< Bidirectional >::value_type >( )
) );
}