Рубрики

QuickSort Tail Call Optimization (Сокращение места наихудшего случая для регистрации n)

Необходимое условие: устранение Tail Call

В QuickSort функция разделения на месте, но нам нужно дополнительное пространство для рекурсивных вызовов функций. Простая реализация QuickSort делает два вызова сама себе и в худшем случае требует O (n) места в стеке вызовов функций.
Худший случай случается, когда выбранная опорная точка всегда делит массив так, что одна часть имеет 0 элементов, а другая часть имеет n-1 элементов. Например, в приведенном ниже коде, если мы выберем последний элемент как сводный, мы получим наихудший случай для отсортированных массивов (см. Это для визуализации)

/ * Простая реализация QuickSort, которая делает два

   два рекурсивных вызова. * /

void quickSort(int arr[], int low, int high)

{

    if (low < high)

    {

        / * pi - индекс разделения, теперь arr [p]

           в нужном месте * /

        int pi = partition(arr, low, high);

   

        // Отдельно сортируем элементы перед

        // раздел и после раздела

        quickSort(arr, low, pi - 1);

        quickSort(arr, pi + 1, high);

    }

}
// Смотрите ниже ссылку для полного выполнения кода
// http://geeksquiz.com/quick-sort/

Можем ли мы уменьшить вспомогательное пространство для стека вызовов функций?
Мы можем ограничить вспомогательное пространство O (Log n). Идея основана на устранении хвостовых вызовов . Как видно из предыдущего поста , мы можем преобразовать код так, чтобы он делал один рекурсивный вызов. Например, в приведенном ниже коде мы преобразовали приведенный выше код в цикл while и сократили количество рекурсивных вызовов.

/ * Быстрая сортировка после удаления хвостового вызова с использованием цикла while * /

void quickSort(int arr[], int low, int high)

{

    while (low < high)

    {

        / * pi - индекс разделения, теперь arr [p]

           в нужном месте * /

        int pi = partition(arr, low, high);

  

        // Отдельно сортируем элементы перед

        // раздел и после раздела

        quickSort(arr, low, pi - 1);

  

        low = pi+1;

    }

}
// Смотрите ниже ссылку для полного выполнения кода
// https://ide.geeksforgeeks.org/qrlM31

Хотя мы сократили количество рекурсивных вызовов, приведенный выше код все еще может использовать O (n) вспомогательное пространство в худшем случае. В худшем случае, возможно, что массив разделен таким образом, что первая часть всегда имеет n-1 элементов. Например, это может произойти, когда последний элемент выбран как сводный, а массив отсортирован в порядке убывания.

Мы можем оптимизировать приведенный выше код, чтобы сделать рекурсивный вызов только для меньшей части после разбиения. Ниже приведена реализация этой идеи.

Дальнейшая оптимизация:

/ * Для этой быстрой сортировки требуется O (Log n) вспомогательное пространство в

   худший случай. * /

void quickSort(int arr[], int low, int high)

{

    while (low < high)

    {

        / * pi - индекс разделения, теперь arr [p]

           в нужном месте * /

        int pi = partition(arr, low, high);

  

        // Если левая часть меньше, то повторяется для левой

        // разделяем и обрабатываем правую часть итеративно

        if (pi - low < high - pi)

        {

            quickSort(arr, low, pi - 1);

            low = pi + 1;

        }

  

        // Остальное повторяется для правой части

        else

        {

            quickSort(arr, pi + 1, high);

            high = pi - 1;

        }

    }

}
// Смотрите ниже ссылку для полного выполнения кода
// https://ide.geeksforgeeks.org/LHxwPk

В приведенном выше коде, если левая часть становится меньше, мы делаем рекурсивный вызов для левой части. Остальное за правую часть. В худшем случае (для пробела), когда обе части имеют одинаковые размеры во всех рекурсивных вызовах, мы используем O (Log n) дополнительное пространство.

Ссылка:
http://www.cs.nthu.edu.tw/~wkhon/algo08-tutorials/tutorial2b.pdf

Эта статья предоставлена Dheeraj Jain . Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

Рекомендуемые посты:

QuickSort Tail Call Optimization (Сокращение места наихудшего случая для регистрации n)

0.00 (0%) 0 votes