Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы сортировки.doc
Скачиваний:
35
Добавлен:
05.11.2018
Размер:
228.35 Кб
Скачать

Сортировка вставками: анализ

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

Как измерять размер входа (input size)? Это зависит от конкретной задачи. В одних случаях размером разумно считать число элементов на входе (сортировка, преобразование Фурье). В других более естественно считать размером общее число битов, необходимое для представления всех входных данных. Иногда размер входа измеряется не одним числом, а несколькими (например, число вершин и число рёбер графа).

Временем работы (running time) алгоритма мы называем число элементарных шагов, которые он выполняет–вопрос только в том, что считать элементарным шагом. Мы будем полагать, что одна строка псевдокода требует не более чем фиксированного числа операций (если только это не словесное описание каких-то сложных действий – типа «отсортировать все точки по координате»). Мы будем различать также вызов (call) процедуры (на который уходит фиксированное число операций) и её исполнение (execution), которое может быть долгим.

Итак, вернёмся к процедуре insertion-sort и отметим около каждой строки её стоимость (число операций) и число раз, которое эта строка исполняется. Для каждого j от 2 до п (здесь п = length[A] – размер массива) подсчитаем, сколько раз будет исполнена строка 5, и обозначим это число через /.у. (Заметим, что строки внутри цикла выполняются на один раз меньше, чем проверка, поскольку последняя проверка выводит из цикла.)

Строка стоимостью с, повторенная ш раз, дает вклад сш в общее число операций. (Для количества использованной памяти этого сказать нельзя!) Сложив вклады всех строк, получим

Как мы уже говорили, время работы процедуры зависит не только от л, по и от того, какой именно массив размера п подан ей на вход. Для процедуры insertion-sort наиболее благоприятен случай, когда массив уже отсортирован. Тогда цикл в строке 5 завершается после первой же проверки (поскольку г\ ^ key при i = j – 1), так что все tj равны 1, и общее время есть

Таким образом, в наиболее благоприятном случае время Т(п), необходимое для сортировки массива размера л, является линейной функцией (linear function) от n, т.е. имеет вид Т[п) = an + b для некоторых констант а и b. (Эти константы определяются выбранными значениями c1,..., c8.)

Если же массив расположен в обратном (убывающем) порядке, время работы процедуры будет максимальным: каждый элемент A[j] придётся сравнить со всеми элементами A[1],. .. .A[j – 1]. При этом tj = j. Поскольку

Время работы в худшем случае и в среднем

Итак, мы видим, что время работы в худшем случае и в лучшем случае могут сильно различаться. Большей частью нас будет интересовать время работы в худшем случае (worst-case running time), которое определяется как максимальное время работы для входов данного размера. Почему? Вот несколько причин.

• Зная время работы в худшем случае, мы можем гарантировать, что выполнение алгоритма закончится за некоторое время, даже не зная, какой именно вход (данного размера) попадётся.

• На практике «плохие» входы (для которых время работы близко к максимуму) могут часто попадаться. Например, для базы данных плохим запросом может быть поиск отсутствующего элемента (довольно частая ситуация).

• Время работы в среднем (о котором мы говорим дальше) может быть довольно близко к времени работы в худшем случае. Пусть, например, мы сортируем случайно расположенные п чисел с помощью процедуры insertion-sort. Сколько раз придётся выполнить цикл в строках 5-8? В среднем около половины элементов массива A[1..j–1] больше A[j], так что tj в среднем можно считать равным j/2, и время Т(п} квадратично зависит от п.

В некоторых случаях нас будет интересовать также среднее время работы (average-case running time, expexted running time) алгоритма на входах данной длины. Конечно, эта величина зависит от выбранного распределения вероятностей, и на практике реальное распределение входов может отличаться от предполагаемого, которое обычно считают равномерным. Иногда можно добиться равномерности распределения, используя датчик случайных чисел.

Порядок роста

Наш анализ времени работы процедуры insertion-sort был основан на нескольких упрощающих предположениях. Сначала мы предположили, что время выполнения i-й строки постоянно и равно Сi. Затем мы огрубили оценку до an2 + bп + с. Сейчас мы пойдём ещё дальше и скажем, что время работы в худшем случае имеет порядок роста (rate of growth, order of growth) n2, отбрасывая члены меньших порядков (линейные) и не интересуясь коэффициентом при ni. Это записывают так: Т(п) = O(n2) (подробное объяснение обозначений мы отложим до следующей главы).

Алгоритм с меньшим порядком роста времени работы обычно предпочтительнее; если, скажем, один алгоритм имеет время работы O(n2), а другой- O(n3), то первый более эффективен (по крайней мере для достаточно длинных входов; будут ли реальные входы таковыми – другой вопрос).