
- •Глава 2. Сортировка и порядковые статистики
- •Отношение на множестве целых чисел является линейным порядком, а включение множеств нет.
- •Алгоритм 8. Лексикографической сортировки
- •Алгоритм 9. Лексикографической сортировки строк различной длины
- •Алгоритм 10.1. Построение сортирующего дерева
- •Алгоритм 10.2. Сортдеревом
- •Алгоритм 11. Быстрсорт
- •Алгоритм 12.1. Нахождение k-го наименьшего элемента
- •Алгоритм 12.2. Нахождение k-го наименьшего элемента со случайным выбором разбивающего элемента
- •Int Selection(int array[], unsigned order, unsigned init, unsigned fin);
- •Void main()
- •Int result, result1, *array, *array1;
- •Int Selection(int array[], unsigned order, unsigned init, unsigned fin)
- •Int divisor, temp;
Алгоритм 10.2. Сортдеревом
Вход. Массив элементов Array[i], 1 i n.
Выход. Элементы массива Array, организованные в порядке возрастания.
Метод. Применяется алгоритм 10.1., т.е. процедура Build_heap и процедура Heapify.
Процедура Heapsort(Array,n)
{
Build_heap(Array, n);
for (index=n; index=2; index--)
{
Переставить Array[1] и Array[i];
Heapify(Array, 1, index–1);
}
}
Теорема 5. Алгоритм 10.2. упорядочивает последовательность из n элементов за время O(nlogn). Следовательно, он имеет временную сложность O(nlogn).
Доказательство данной теоремы несложно осуществить по индукции и предлагается читателям в качестве упражнения. Следовательно, алгоритм Сортдеревом имеет временную сложность O(nlogn).
2.4. Сортировка (Быстрсорт) – упорядочение за среднее время O(nlogn)
Для многих сортирующих алгоритмов более реалистичной мерой временной сложности, чем работа для наихудшего возможного случая, является усреднённое время работы. В случае сортировки с помощью деревьев решений никакой сортирующий алгоритм не может иметь среднюю временную сложность, существенно меньшую nlogn. Однако известны алгоритмы сортировки, которые работают в худшем случае cn2 времени, где c – некоторая константа, но среднее время работы которых относит их к лучшим алгоритмам сортировки. Примером такого алгоритма служит алгоритм Быстрсорт.
Чтобы можно было рассуждать о среднем времени работы алгоритма, необходимо задать вероятностное распределение входов. Для сортировки естественно допустить, что любая перестановка упорядочиваемой последовательности равновероятна в качестве входа. При таком допущении можно оценить снизу среднее число сравнений, необходимых для упорядочения последовательности из n элементов.
Общий метод
состоит в том, чтобы поставить в
соответствие каждому листу v
дерева решений вероятность быть
достигнутым при данном входе. Зная
распределение вероятностей на входах,
можно найти вероятности, поставленные
в соответствие листьям. Таким образом,
можно определить среднее число сравнений,
производимых данным алгоритмом
сортировки, если вычислить сумму
,
взятую по всем листьям дерева решений
данного алгоритма, в которой pj
– вероятность достижения j-го
листа, а dj
– его глубина. Это число называется
средней глубиной дерева решений
(expected depth
of decision
tree).
Известна в теории алгоритмов следующая теорема.
Теорема 6. В предположении, что все перестановки n-элементной последовательности появляются на входе с равными вероятностями, любое дерево решений, упорядочивающее последовательность из n элементов, имеет глубину не менее logn!. Следствием этой теоремы будет тот факт, что любая сортировка с помощью сравнений выполняется в среднем не менее чем за cnlogn сравнений для некоторой постоянной c > 0.
Доказательство. Обозначим через D(T) сумму глубин листьев двоичного дерева T. Пусть Dm(T) – её наименьшее значение, взятое по всем двоичным деревьям T с m листьями. Докажем по индукции, что Dm(m) mlogm.
Базис, т.е. случай m=1, тривиален. Допустим, что предположение индукции верно для всех значений m, меньших k. Рассмотрим дерево решений T с k листьями. Оно состоит из корня с левым поддеревом Ti с i листьями и правым поддеревом Tk–i с k–i листьями при некотором i, 1 i n. Ясно, что
D(T) = i + D(Ti) + (k–i) + D(Tk–i)
Поэтому наименьшее значение D(T) задаётся равенством
Dm(T)
=
[k
+
D(Ti)
+ D(Tk–i)]
или
Dm(k)
=
[k
+
D(i)
+ D(k–i)]
Учитывая предположение индукции, отсюда получается
Dm(k)
k+[
ilogi
+ (k–i)log(k–i)]
Легко показать, что минимум достигается при i=k/2. Следовательно,
Dm(k) k+klog(k/2) = klogk.
Таким образом, Dm(m) mlogm для всех m1.
Теперь докажем утверждение, что дерево решений, упорядочивающее n случайных элементов, имеет не менее листьев. Более того, в точности n! листьев появляются с вероятностью 1/n! каждый, а остальные – с вероятностью 0. Не изменяя средней глубины дерева T, можно удалить из него все узлы, которые являются предками только листьев вероятности 0. Тогда останется только дерево T с n! листьями, каждый из которых достигается с вероятностью 1/n!. Т.к. D(T) n!logn!, то средняя глубина дерева T (а значит, и T) не меньше (1/n!)n!logn! = logn!.
Существует эффективный алгоритм, называемый Быстрсорт, среднее время работы которого хотя и ограничено снизу функцией cnlogn для некоторой постоянной c (как у всякого алгоритма с помощью сравнений), но составляет лишь часть времени работы других известных алгоритмов при их реализации на большинстве существующих машин. В худшем случае данный алгоритм имеет квадратичную скорость работы, но для большинства практических случаев это несущественно.