Может кто-нибудь объяснить мне эту версию быстрой сортировки (где центральная точка выбрана)? - PullRequest
0 голосов
/ 06 июня 2019

Я недавно вернулся к быстрой сортировке. Раньше я делал поворот, выбирая последний или первый элемент из списка. Однако другой я наткнулся на этот фрагмент, где ось была выбрана с середины. Я знаю, что то, как рассчитывается пивот, влияет только на производительность алгоритма. Но я просто не могу понять этот алгоритм разделения.

Полагаю, для меня проблема в понимании алгоритма разбиения состоит в том, что, я думал, он должен сделать результирующий массив таким, чтобы все элементы, меньшие, чем сводка, уходили влево, а все элементы, большие, чем сводка, переходили к право. Однако этот алгоритм разделения не всегда достигает этого.

private static void quickSort (int[] array, int left, int right) {
    int index = partition(array, left, right);

    //Sort left half
    if (left < index - 1)
        quickSort(array, left, index - 1);

    //Sort right half
    if (index < right)
        quickSort(array, index , right);
}

private static int partition (int array[], int left, int right) {
    int pivot = array[(left + right) / 2]; //Pick pivot point
    while (left <= right) {
        //Find element on left that should be on right
        while (array[left] < pivot)
            left++;

        //Find element on right that should be on left
        while (array[right] > pivot)
            right--;

        //Swap elements and move left and right indices
        if (left <= right) {
            int temp = array[left];
            array[left] = array[right];
            array[right] = temp;
            left++;
            right--;
        }
    }
    return left;
}

если я задаю алгоритму разбиения массив [1,0,-1,3,5,10,-5], то опорная точка будет 3, но после разбиения массив будет [ 1, 0, -1, -5, 5, 10, 3 ]. Я просто не могу понять это, потому что не похоже, что раздел делает что-то значимое. Он не разделил массив пополам.

Ответы [ 2 ]

1 голос
/ 07 июня 2019

Код представляет собой вариант схемы разбиения Hoare, где каждый шаг разбиения приводит к тому, что все элементы pivot, но элементы == pivot, включая сам pivot, могут заканчиваться где угодно слева или правый раздел, в зависимости от шаблона данных. Вот почему в рекурсивных вызовах используются index-1 и index, поскольку возвращаемый индекс не соответствует сводной точке, поэтому его нельзя исключить из рекурсивных вызовов.

В этом примере на первом шаге разбиения left увеличивается до 3, так как array [{0,1,2}] pivot, приводящий к свопу (array [3], array [6]), установке массива [3] = -5 и array [6] = 3 (pivot).

0 голосов
/ 06 июня 2019

Шарнир смещен вправо, вне пути последующей сортировки. Левый и правый указатели соответственно отрегулированы. Пересмотрите этот массив на три части: влево, вправо и поворот. Вместо

[ 1, 0, -1, -5, 5, 10, 3 ]

у вас есть

[ 1, 0, -1, -5], [5, 10], [ 3 ]

Все в left меньше оси; все в right больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...