I was curious how std:next_permutation
was implemented so I extracted the the gnu libstdc++ 4.7
version and sanitized the identifiers and formatting to produce the following demo...
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
template<typename It>
bool next_permutation(It begin, It end)
{
if (begin == end)
return false;
It i = begin;
++i;
if (i == end)
return false;
i = end;
--i;
while (true)
{
It j = i;
--i;
if (*i < *j)
{
It k = end;
while (!(*i < *--k))
/* pass */;
iter_swap(i, k);
reverse(j, end);
return true;
}
if (i == begin)
{
reverse(begin, end);
return false;
}
}
}
int main()
{
vector<int> v = { 1, 2, 3, 4 };
do
{
for (int i = 0; i < 4; i++)
{
cout << v[i] << " ";
}
cout << endl;
}
while (::next_permutation(v.begin(), v.end()));
}
The output is as expected: http://ideone.com/4nZdx
My questions are: How does it work? What is the meaning of i
, j
and k
? What value do they hold at the different parts of execution? What is a sketch of a proof of its correctness?
Clearly before entering the main loop it just checks the trivial 0 or 1 element list cases. At entry of the main loop i is pointing to the last element (not one past end) and the list is at least 2 elements long.
What is going on in the body of the main loop?
while (true)
statement is an infinite loop, the function only returns via the inner return statements the loop encloses. – Munsey