Интерес к алгоритмам сортировки в значительной степени обусловлен именно тем, что ряд задач с участием списков решаются существенно проще, если списки отсортированы. Понятно, что временная эффективность алгоритма, включающего в качестве этапа сортировку, может зависеть от эффективности использованного алгоритма сортировки.
Проверка уникальности элементов массива.
Алгоритм на основе грубой силы для проверки того, что все элементы массива различны, попарно сравнивает все элементы этого массива, пока не будут найдены два одинаковых либо пока не будут пересмотрены все возможные пары. В наихудшем случае эффективность такого алгоритма равна Θ.
К решению задачи можно подойти и по-другому — сначала отсортировать массив, а затем сравнивать только последовательные элементы: если в массиве есть одинаковые элементы, то они должны следовать в отсортированном массиве один за другим.
Алгоритм Uniqueness (A)
// Входные данные: Массив A[0...n-1]
// Выходные данные: true, если в A нет одинаковых элементов,
// и false, если есть
Сортировка массива A
for i in [0...n-2] do
quad if A[i] =A[i + 1]
quad quad quad return false
return true
Время работы данного алгоритма представляет собой сумму времени,
затраченного на сортировку, и времени на проверку соседних элементов. Поскольку
для сортировки требуется как минимум n log n сравнений, а для проверки
соседних элементов — не более n-1, именно сортировка и определяет общую
эффективность алгоритма:
T(n) = T_{"sort"}(n) + T_{"scan"}(n) in Theta (n log n) + Theta (n) = Theta (n log n).
Модой называется значение, которое встречается в данном списке чаще других. Например, в случае значений 5, 1,5, 7, 6, 5, 7 модой является значение 5 (если одинаково часто встречается несколько значений, модой может быть выбрано любое из них). Алгоритм на основе грубой силы сканирует весь список и вычисляет количество появлений в списке каждого из значений, из которых выбирается наибольшее.
При каждой итерации i-ый элемент исходного списка сравнивается со всеми значениями в списке для подсчета количества.
В результате количество сравнений равно:
C(n)=sum_{i=1}^n n=n^2 in Theta(n^2).
Рассмотрим альтернативный вариант, начинающийся с сортировки списка. В таком случае все равные значения будут соседствовать друг с другом, и для вычисления моды надо только найти наибольшую подпоследовательность одинаковых соседних значений в отсортированном списке.
Алгоритм Mode (A)
// Входные данные: Массив A[0...n-1]
// Выходные данные: Мода массива
Сортировка массива A
i larr 0 // Текущая позиция
mcount larr 0 // Максимальное количество одинаковых элементов
while i < n do
quad l en larr 1; val larr A[i]
quad while i+l en < n and A[i+l en] = val do
quad quad quad l en larr l en + 1
quad if l en > mcount
quad quad quad mcount larr l en; m ode larr val
quad i larr i+l en
return m ode
Время работы алгоритма определяется временем сортировки, поскольку время выполнения остальной части алгоритма — линейное. Следовательно, при использовании сортировки, принадлежащей классу эффективности n log n, эффективность описанного алгоритма будет выше эффективности алгоритма с использованием грубой силы.
Рассмотрим поиск данного значения K в массиве из n
элементов. Решение с использованием грубой силы —
последовательный поиск — требует в наихудшем случае n сравнений. Если
массив предварительно отсортировать, то применение бинарного поиска приведет
к |__ log_2 n __| + 1 сравнений в наихудшем случае. Даже при использовании
максимально эффективной сортировки класса n log n общее время работы алгоритма
в наихудшем случае составит
T(n) = T_{"sort"} (n) + T_{"search"}(n) = Theta(n log n) + Theta(log n) = Theta(n log n),
что хуже, чем в случае последовательного поиска.
То же самое можно сказать и об эффективности в среднем случае.
Конечно, если поиск требуется выполнять неоднократно, то затраты времени на сортировку могут оказаться оправданными.