Ich war neugierig, wie std:next_permutation
es implementiert wurde, also extrahierte ich die gnu libstdc++ 4.7
Version und bereinigte die Bezeichner und Formatierungen, um die folgende Demo zu erstellen ...
#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()));
}
Die Ausgabe ist wie erwartet: http://ideone.com/4nZdx
Meine Fragen sind: Wie funktioniert es? Was ist der Sinn i
, j
und k
? Welchen Wert haben sie für die verschiedenen Teile der Ausführung? Was ist eine Skizze eines Beweises für seine Richtigkeit?
Es ist klar, dass vor dem Eintritt in die Hauptschleife nur die trivialen 0- oder 1-Elementlistenfälle überprüft werden. Beim Eintritt in die Hauptschleife zeigt i auf das letzte Element (nicht auf ein hinteres Ende) und die Liste ist mindestens 2 Elemente lang.
Was ist im Körper der Hauptschleife los?