В заключение приведем рекурсивный алгоритм сортировки массива, который на практике является одним из самых быстрых. Пусть дан массив . Рекурсивная процедура sort(l,r:integer) сортирует участок массива с индексами из полуинтервала ,то есть ,не затрагивая остального массива.
procedure sort (l,r: integer); begin | if (l = r) then begin | | ничего делать не надо - участок пуст | end else begin | | выбрать случайное число s в полуинтервале (l,r] | | b := a[s] | | переставить элементы сортируемого участка так, чтобы | | сначала шли элементы, меньшие b - участок (l,ll] | | затем элементы, равные b - участок (ll,rr] | | затем элементы, большие b - участок (rr,r] | | sort (l,ll); | | sort (rr,r); | end; end;Разделение элементов сортируемого участка на три категории (меньшие, равные, больше) рассматривалась в главе 1, с. (это можно сделать за время, пропорциональное длине участка). Конечность глубины рекурсии гарантируется тем, что длина сортируемого участка на каждом уровне рекурсии уменьшается хотя бы на 1 .
7.4.7. (Для знакомых с основами теории вероятностей). Доказать,
что математическое ожидание числа операций при работе этого
алгоритма не превосходит , причем константа C не
зависит от сортируемого массива.
7.4.8. Имеется массив из n различных целых чисел
и число k . Требуется найти k -ое
по величине число в этом массиве, сделав не более Cn
действий, где C -- некоторая константа, не зависящая от
k и n .
[Указание. Изящный (хотя практически и бесполезный -- константы слишком велики) способ сделать это таков:
А. Разобьем наш массив на n/5 групп, в каждой из которых по 5 элементов. Каждую группу упорядочим.
Б. Рассмотрим средние элементы всех групп и перепишем их в массив из n/5 элементов. С помощью рекурсивного вызова найдем cредний по величине элемент этого массива.
В. Сравним этот элемент со всеми элементами исходного массива: они разделятся на большие его и меньшие его (и один равный ему). Подсчитав количество тех и других, мы узнаем, в какой из этих частей должен находится искомый (k -ый) элемент и каков он там по порядку.
Г. Применим рекурсивно наш алгоритм к выбранной части.
Пусть T(n) -- максимально возможное число действий, если этот способ применять к массивам из не более чем n элементов (k может быть каким угодно). Имеем оценку: Последнее слагаемое объясняется так: при разбиении на части каждая часть содержит не менее 0,3n элементов. В самом деле, если x -- средний из средних, то примерно половина всех средних меньше x . А если в пятерке средний элемент меньше x , то еще два заведомо меньше x . Тем самым по крайней мере 3/5 от половины элементов меньше x .
Теперь по индукции можно доказать оценку (решающую роль при этом играет то обстоятельство, что ). ]