C randomized pivot quicksort (improving the partition function)

后端 未结 2 566
小鲜肉
小鲜肉 2021-01-13 22:23

I\'m a computer science student (just started), I was working on writing from pseudocode a randomized pivot version of Quicksort. I\'ve written and tested it, and it all wor

2条回答
  •  失恋的感觉
    2021-01-13 22:55

    There are multiple ways to partition for quicksort, the following being likely the simplest I can muster. Generally two schools of partitioning are used:

    1. The Squeeze - collapses both ends of the sequence until a suitable swap pair is found, then swaps two elements into proper sides of the partition. Not trivial to implement, but can be more efficient (reduced swap count) than the alternative...
    2. The Sweep - uses a single left to right (or right to left) sweep the values, swapping values to an incrementing pivot index that moves as the algorithm runs. Very simple to implement, as you'll see below.

    I prefer the Sweep algorithm for people learning quicksort and partitioning only because it is so dead-simple to implement. Both can be implemented to perform in-place partitioning, as is the case in the implementation below. At no time except in swap() will you see a value stored in temp-storage.

    Using a random pivot selection is only a small part of this. The following shows how to initialize the random number generator, and demonstrates likely the simplest partition algorithm and quicksort usage therein you're going to find.

    It demonstrates, among other things, that in C/C++, you don't need both ends of a partition since simple pointer arithmetic can be used to adjust the "top" half of a partition. See the quicksort() function for how this is done.

    #include 
    #include 
    #include 
    
    void swap(int *lhs, int *rhs)
    {
        if (lhs == rhs)
            return;
    
        int tmp = *lhs;
        *lhs = *rhs;
        *rhs = tmp;
    }
    
    int partition(int ar[], int len)
    {
        int i, pvt=0;
    
        // swap random slot selection to end.
        //  ar[len-1] will hold the pivot value.
        swap(ar + (rand() % len), ar+(len-1));
        for (i=0; i

    Output (varies, obviously)

    32 49 42 49 5 18 41 48 22 33 40 27 12 47 41 6 50 27 8 7 
    5 6 7 8 12 18 22 27 27 32 33 40 41 41 42 47 48 49 49 50 
    

    Note: this does NOT account for modulo bias for using rand() % len, and frankly it would be overkill to do so for this example. If it were critical, I would use another generator entirely. An outstanding discussion for methods of choosing random pivot locations for quicksort partitioning can be found at this post on this site, including many links to different methods. I suggest reviewing it.

提交回复
热议问题