
- •Введение
- •Содержание и структура пособия
- •Задачи поиска в информатике
- •Задача поиска в таблице
- •Поиск в массивах
- •Линейный поиск
- •Бинарный поиск
- •Вопросы и упражнения
- •Алгоритмы сортировки массивов
- •Задачи сортировки таблиц и массивов
- •Простые алгоритмы сортировки
- •Алгоритм пузырька (BubbleSort)
- •Алгоритм выбора (SelectionSort)
- •Алгоритм вставок (InsertionSort)
- •Общая характеристика простых алгоритмов
- •Алгоритм Шелла (ShellSort)
- •Алгоритм быстрой сортировки (QuickSort)
- •Алгоритм пирамидальной сортировки (HeapSort)
- •Алгоритмы сортировки слиянием (MergeSort)
- •Задача внешней сортировки
- •Сравнение алгоритмов сортировки
- •Вопросы и упражнения
- •Сортировка и поиск с использованием деревьев
- •Задача поиска со вставкой
- •Бинарные деревья поиска
- •Var t: Tree; {Кореньдерева}
- •X: KeyType; {Искомый ключ}
- •Var found: Boolean {Найдено или вставлено?}
- •Страничные деревья поиска
- •Использование b-деревьев в базах данных
- •Вопросы и упражнения
- •Специальные методы сортировки и поиска
- •Поразрядная сортировка
- •Поиск в словаре и нагруженные деревья
- •Вопросы и упражнения
- •Хеширование
- •Основные понятия хеширования
- •Способы построения хеш-функций
- •Общие требования к хеш-функциям
- •Алгоритм деления
- •Алгоритм середины квадрата
- •Алгоритм умножения
- •Хеширование строковых ключей
- •Методы разрешения коллизий
- •Алгоритм линейных проб
- •Алгоритм квадратичных проб
- •Алгоритм двойного хеширования
- •Алгоритм списков в динамической памяти
- •Алгоритм Уильямса
- •Эффективность хеширования и сравнение с другими методами поиска
- •Вопросы и упражнения
- •Дополнительные вопросы поиска
- •Определение порядковых статистик
- •Задача поиска в строке
- •Постановка задачи и «прямое» решение
- •Алгоритм Кнута, Морриса и Пратта
- •Алгоритм Бойера – Мура
- •Вопросы и упражнения
- •Заключение
- •Библиографический список
Сравнение алгоритмов сортировки
Подведем некоторые итоги. В данном разделе были рассмотрены наиболее известные (и лучшие) алгоритмы сортировки массивов. Эти алгоритмы разделяются на две группы: простые алгоритмы (сюда относятся «пузырек», выбор и вставки) и усовершенствованные ( алгоритмы Шелла, быстрой сортировки, пирамидальной сортировки и сортировки слиянием).
Общим недостатком простых алгоритмов является их слишком медленная работа на больших массивах данных. Это подтверждается как практикой использования, так и теоретической оценкой T(n) = O(n2). Усовершенствованные алгоритмы работают гораздо быстрее, причем на очень больших массивах различие может достигать многих тысяч раз.
Не следует делать из этого вывод, что всегда нужно применять только усовершенствованные алгоритмы. Для массивов малого размера различие в числе итераций незначительно, при этом даже возможно, что простые алгоритмы будут работать быстрее за счет более быстрого выполнения каждой итерации.
Где проходит граница между «маленькими» и «большими» массивами? Этот вопрос трудно решить теоретически, он должен решаться скорее на основе экспериментов, а также опыта и интуиции программиста.
Возникает также следующий вопрос. Есть ли основания останавливаться на пути усовершенствования алгоритмов сортировки, успокоившись на оценке T(n) = O(n·log(n))? Нельзя ли придумать алгоритм, имеющий существенно меньшую оценку?
Оказывается, что в классе алгоритмов, основанных на операциях сравнения ключей и перестановки записей, получить лучшую (в смысле O-большое) оценку нельзя. Чтобы доказать это, заметим, что любой исходный (несортированный) массив можно рассматривать как некоторую перестановку элементов сортированного массива. Для простоты будем считать, что все элементы массива различны, тогда эта перестановка единственна. Задача заключается в том, чтобы выполнить обратную перестановку, «привести в порядок» элементы. Очевидно, для правильного выполнения обратной перестановки нужно, как минимум, знать, какая именно из всех возможных перестановокnэлементов имеет место в случае данного массива. Как известно, число таких перестановок равноn!(факториалу отn). Поставим вопрос: какое минимальное число сравнений ключей следует выполнить, чтобы гарантированно определить, какая изn!перестановок имеет место? Одно сравнение на «больше/меньше» позволяет, в лучшем случае, разбить множество перестановок на две равные половины. Для того чтобы при помощи таких разбиений наверняка выделить единственную перестановку, придется выполнить не менее, чемlog2(n!)сравнений. Из математики известно, что при большихnзначение факториала можно приближенно определить по формуле Стирлинга:
Отсюда
Как обычно, при переходе к оценке «в смысле O-большое» от формулы оставлен только главный член.
Полученная оценка показывает, что ни один алгоритм не позволит для числа сравнений получить лучшую оценку, чем O(n·log(n)). С учетом присваиваний оценка тем более не может улучшиться. Таким образом, дальнейшие исследования могут, конечно, привести к разработке лучших алгоритмов сортировки, но только в рамках оценкиTmax(n) = O(n·log(n)).
А что же тогда означает сделанная выше оговорка относительно «класса алгоритмов, основанных на операциях сравнения ключей и перестановки записей»? Возможны ли какие-то иные алгоритмы сортировки? Эти вопросы будут рассмотрены ниже, в разделах 5 и 6.