1

I am trying to understand how the Heap's algorithm for permutations works but I find it very hard to understand. I haven't found an example of recursion tree to explain how the code works. Can anyone provide one for me?

Let's say I want to compute all permutations of the list [1,2,3,4] in python. I know how to implement the algorithm in python,

def heapPermutation(a, size):
    if size == 1:
        return
    for i in range(size):
        heapPermutation(a,size-1)
            
        if size % 2 == 0:
            a[i],a[size-1] = a[size-1],a[i]
        else:
            a[0],a[size-1] = a[size-1],a[0]

but still I get confused by the recursive calls.

  • This is a particularly tricky question, since your function here takes advantage of both recursivity and the mutability of the argument `a`. Maybe using a visual debugger to follow along would help you find out how all of this works ? – Baptiste Prevot Mar 09 '22 at 23:18
  • 2
    That's not a correct implementation of Heap's Algorithm, even if you correct the typo in `for i in range(2):`. (I see that the Wikipedia page on Heap's algorithm has been defaced again. Sigh.) – rici Mar 09 '22 at 23:52
  • @rici ops, let me correct the typo – user2874909 Mar 10 '22 at 00:47
  • 1
    Cool. But it's still not the correct implementation. Sadly, that particular incorrect implementation is very widespread. See https://stackoverflow.com/a/29044942/1566221 – rici Mar 10 '22 at 01:05
  • @rici Doing some searching, Sedgewick now has his [original 1977 paper](https://sedgewick.io/wp-content/themes/sedgewick/papers/1977Permutation.pdf) with Heap's algorithm free on his website. Might be useful to OP here, and/or if you want to add that reference to your great answer in the other thread. – kcsquared Mar 10 '22 at 01:10
  • @kcsquared: Cool, I'll add that reference. Now if only he would correct the mistake in his slides... – rici Mar 10 '22 at 01:20
  • @rici yes, I read the comment and indeed I deleted my comment here :) However, I am very familiar with generators and, since the algorithm is already confusing, it's not easy for me to understand how it works... I will try to study it – user2874909 Mar 10 '22 at 02:13
  • @user2874909: Maybe you meant that you're *not* very familiar with generators? These days I would probably write `for hp in _heap_perm_(n-1, A): yield hp` as `yield from _heap_perm_(n-1, A)` (again, I was mimicking the code in the OP). `yield from` is the generator equivalent of a recursive call, which is the main thing you need to know. – rici Mar 10 '22 at 02:20
  • Python generators are really the way to go in combinatorics, and they're not intrinsically different from recursion. But leaving that aside, it should be clear why the code as you originally wrote it is incorrect. The point of Heap's algorithm is that it produces a Gray sequence; that is, successive permutations are as similar as possible to each other. In particular, each permutation differs from the previous one only in a single swap. From that, it is clear that the algorithm should never swap twice without producing a permutation.... – rici Mar 10 '22 at 02:36
  • From that, it should be clear that the recursive call must not end with a swap, since recursive calls are immediately followed by a swap. The recursive call can only finish by either producing a new permutation or by a recursive call which will finish by producing a new permutation, etc. Similarly, the recursive call cannot start by swapping. So it must either produce a new permutation (if n == 1) or it must start and end with a recursive call. – rici Mar 10 '22 at 02:38
  • This apparently obvious point seems to have flown over the heads of the myriads of people who have defaced that Wikipedia page or otherwise published incorrect versions of this beautiful algorithm. Understanding the high-level structure of this function is therefore probably a good way to get a feeling for the nature of recursion. – rici Mar 10 '22 at 02:41

0 Answers0