0

I was recently instructed in one of my algorithm classes to use Knuth's algorithm to create permutations stored in a malloc'd array.

Here is the setup:

array is a pointer to a malloced array holding the permutation. It is intially storing n values, each position holding the index + 1.

So if n was 10, the array would initially be:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

The "rand" variable holds some variable from 1 to n. (In this example, 1-10).

Swap is supposed to be a function that does a bit-exclusive OR swap (XOR).

The end result is supposed to be some permutation of 1-n.

So [5, 6, 2, 8, 7, 4, 1, 3, 10, 9] would be valid as one possible permutation.

However, [1, 1, 5, 7, 8, 2, 3, 5, 5, 6] would not be valid, since it's not a permutation. It has duplicates.

But I can't make heads or tails of this code we were told to use:

for(i = 1; i < n; i++) {
    swap(&array[i], &a[rand]);
}

So we start off on the second element of the array. (i = 1)

We then attempt to XOR two paramenters:

First: &array[i]

That is the address of a pointer to the malloced array. (A double pointer, right?)

And the second parameter is the exact same thing. An address of a pointer to the malloced array.

How and why the heck am I supposed to do XOR on addresses?

What am I not understanding?

Thanks for any and all help!

Tyler Shellberg
  • 1,086
  • 11
  • 28
  • 1
    So your question is basically "what does `&array[i]` mean?"? If so, the answer is "the address of the `i`-th element in `array`". – Oliver Charlesworth Mar 05 '16 at 20:40
  • 1
    You mention `swap` (and apparently it uses `xor`) but fail to show this function. While a XOR swap is a good way to do it, it is *by no means* part of the algorithm you are asking about. Any regular way of swapping ought to work. – Jongware Mar 05 '16 at 20:45
  • C parameters are always pass-by-value, so the subroutine `swap` cannot change the parameters passed back in the calling routine. However, by passing the address of those parameters, the `swap` routine can reference the addresses and change the values at those addresses. – mpez0 Mar 05 '16 at 20:47

1 Answers1

4

Firstly, swap is not supposed to do a bitwise exclusive or. It's supposed to swap.

Usually, that's written:

void swap(int *a, int *b)
{
    int t=*a;
    *a=*b;
    *b=t;
}

But there's a trick using XOR that doesn't require an extra variable. You can implement swap like this:

void swap(int *a, int *b)
{
    *a^=*b;
    *b^=*a;
    *a^=*b;
}

Which is probably what someone meant by doing an XOR in swap.

Secondly, rand has to range from 0 to i, not 1 to n, of you want an unbiased random permutation.

Given rand(x) returns a number in [0,x], you want something like this:

for (int i=n-1; i>0; --i)
{
    j = rand(i);
    if (i!=j)
    {
        swap(&array[i],&array[j]);
    }
}

The way it works is simple: for each array[i], it chooses an element randomly from the ones that haven't already been picked.

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87