Let's look at some permutations:
1 2 3 4 1 2 4 3 1 3 2 4 1 3 4 2 1 4 2 3 1 4 3 2 2 1 3 4 ...
How do we move from one permutation to the next? First, let's look at things a little differently. We can consider elements as numbers and permutations as numbers . Looking at the problem this way , we want to order the permutations / numbers in ascending order .
When we order rooms, we want to "increase them by the minimum amount." For example, when counting, we do not take into account 1, 2, 3, 10, ... because there are 4, 5, ... between them and although 10 is greater than 3, there are no numbers that can be obtained by increasing 3 by a smaller amount. In the above example, we see that 1 remains as the first number for a long time, since there are many reorders of the last 3 “digits” that “increase” the permutation by a smaller amount.
So, when do we finally “use” 1 ? When there is no only permutation of the last three digits.
And when there are no more permutations from the last three digits? When the last 3 digits are in descending order.
Yeah! This is the key to understanding the algorithm. We only change the position of the “figure” when everything on the right is in descending order , because if it is not in descending order, there are even more permutations (that is, we can “increase”, the permutation by a smaller amount).
Now back to the code:
while (true) { It j = i; --i; if (*i < *j) { // ... } if (i == begin) { // ... } }
Of the first two lines in the loop, j is the element, and i is the element in front of it.
Then, if the elements are in ascending order, ( if (*i < *j) ) do something.
Otherwise, if all this is in decreasing order, ( if (i == begin) ), then this is the last permutation.
Otherwise, we continue and see that j and i are substantially reduced.
Now we understand the if (i == begin) , so all we need to understand is the if (*i < *j) .
Also note: “Then, if the elements are in ascending order ...”, which supports our previous observation, we only need to do the figure “when everything is in order in descending order”. The upstream operator if essentially finds the leftmost place, where "everything on the right is in descending order."
Let's look again at some examples:
... 1 4 3 2 2 1 3 4 ... 2 4 3 1 3 1 2 4 ...
We see that when everything to the right of the number is in descending order, we find the next big number and put it in front , and then put the remaining numbers in ascending order .
Take a look at the code:
It k = end; while (!(*i < *--k)) ; iter_swap(i, k); reverse(j, end); return true;
Well, since the things on the right are in descending order to find the “next big digit”, we just need to iterate from the end, which we see in the first three lines of code.
Then we replace the “next largest digit” with a iter_swap() operator, and then, since we know that the digit was the next largest, we know that the numbers on the right are still in descending order, so put it in ascending order, we just need reverse() it.