G
G
gigisarri982021-12-08 15:26:30
PHP
gigisarri98, 2021-12-08 15:26:30

Why does my quicksort work in a non-obvious way?

Hello, I'm studying algorithms in the book "Groaking Algorithms", I write in PHP, now I've reached quick sorting. It seems to me that I more or less understand the principle of the algorithm, however, I cannot understand what is wrong. Here is the working code:

function testsort(array $array) {
    if (count($array) < 2) {
        return $array;
    }

    $elem = [$array[0]];
    $left = [];
    $right = [];

    for ($i = 1; $i < count($array); $i++) {
        if ($array[$i] <= $elem[0]) {
            $left[] = $array[$i];
        } else {
            $right[] = $array[$i];
        }
    }

    return array_merge(testsort($left), $elem, testsort($right));
}


Okay, when the anchor element is the first element of the array, I get it, but when I do the following: Everything breaks. Here is one of the output options when sorting the array [2,4,6,1,5,3]:
$elem = [$array[rand(0, count($array) - 1)]];

array (size=6)
0 => int 3
1 => int 3
2 => int 3
3 => int 4
4 => int 5
5 => int 5


A similar situation is when I, for example, take the last element of the array as a reference.

It’s also not clear to me why the loop should start from one, initially I tried to do from zero, but there was a stack overflow, and googling, I saw a similar solution, but with one instead of zero.

Please explain why this is happening and how to fix it. I could not find a solution to this problem on the Internet, moreover, even in this book, a couple of pages later, it is recommended to take the element in the middle as the pivot element, but I cannot take it, because the cycle breaks at any number other than zero. Thanks in advance!

UPD: correct answer below

Small ps
I wonder why the hell to sit in such rather tricky topics as algorithms (and even in a topic where the language is clearly indicated), if you can’t say anything useful on the case, but you do it with a very smart look? I do not understand the desire to insert your 3 kopecks everywhere if you do not understand the technology and, apparently, the sorting algorithm. I don't remember that the toaster was called "Club of programming mastodons who don't even consider it necessary to answer small and newbie questions".

Answer the question

In order to leave comments, you need to log in

2 answer(s)
G
gigisarri98, 2021-12-09
@gigisarri98

Everything was solved in an elementary way, as I understand it, the cycle reached an iteration, where 2-3 elements remained in the array and broke, because the iteration of the reference element was also included in the cycle. As a result, just explicitly telling the cycle to go further when it reaches the pivot, the problem was solved and everything was sorted. So that it does not filter out the same ones, I created a $temp variable, which serves as a marker if this element has already been iterated over.

function testsort(array $array) {
    if (count($array) < 2) {
        return $array;
    }
    
    $elem = [$array[(int)count($array) / 2]];

    $left = [];
    $right = [];
    $temp = '';

    for ($i = 0; $i < count($array); $i++) {
        if ($array[$i] < $elem[0]) {
            $left[] = $array[$i];
        }

        if ($array[$i] > $elem[0]) {
            $right[] = $array[$i];
        }

        if ($array[$i] == $elem[0]) {
            if ($temp) {
                $left[] = $array[$i];
            } else {
                $temp = $elem[0];
                continue;
            }
        }
    }

    return array_merge(testsort($left), $elem, testsort($right));
}

N
nokimaro, 2021-12-08
@nokimaro

Everything breaks

because when recursively calling the rand() function, it gives a different value and the reference element jumps
$elem = [$array[rand(0, count($array) - 1)]];

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question