- •1. Абстрактный тип данных «Список». Методы реализации списков.
- •2. Абстрактный тип данных «Стек»
- •3. Абстрактный тип данных «Очередь»
- •4. Абстрактный тип данных «Дерево»
- •5. Абстрактный тип данных «Множество». Методы реализации Мн-ств
- •6. Структуры данных, основанные на хеш-таблицах
- •7. Деревья двоичного поиска. Методы их реализации.
- •Алгоритм Хаффмена, пример построения кода.
- •10. Алгоритмы быстрой сортировки
- •9. Сбалансированные и несбалансированные деревья поиска
- •12. Алгоритмы внешней сортировки
- •Методы ускорения операций обработки файловых структур данных.
9. Сбалансированные и несбалансированные деревья поиска
Дерево называется идеально сбалансированным, если все его уровни, за исключением, может быть, последнего, полностью заполнены. В бинарном дереве полностью заполненный уровень n содержит 2n узлов.
Если дерево поиска близко к сбалансированному, то даже в худшем случае за время порядка O(log2n) в нем можно:
Найти вершину с заданным значением или выяснить, что такой вершины нет.
Включить новую вершину.
Исключить вершину.
Среднее время выполнения этих операций будет также близким к O(log2n), так как в идеально сбалансированном дереве при полностью заполненных уровнях на последнем уровне находится больше половины узлов дерева.
Например, последовательность значений 4, 6, 2, 1, 5, 3, 7 дает следующее идеально сбалансированное дерево:
В этом дереве 7 узлов, на последнем уровне находится 4 узла.
Если доступ к одному узлу требует 1 единицу времени, то до узла 4 можно добраться за 1 единицу времени, до 2 и 6 - за 2, до 1, 3, 5, 7 - за 3.
То есть в худшем случае требуется 3 единицы времени, в среднем: (1+2*2+3*4)/7 = 2.4 единицы времени.
Однако значения в последовательности могут идти и в другом порядке, что может привести к построению несбалансированного дерева. В худшем случае можно получить вырожденное дерево, подобное линейному списку.
Например, последовательность значений 1, 7, 2, 6, 3, 5, 4 дает следующее вырожденное дерево:
Р
абота
с таким вырожденным деревом потребует
в худшем случае 7 единиц времени (доступ
к 4), а в среднем: (1+2+3+4+5+6+7)/7 = 4 единицы
времени.
То есть для вырожденного дерева затраты на доступ к узлам в худшем случае имеют порядок O(n), в среднем - O(n/2). Разница во времени доступа будет гораздо заметнее при большем числе узлов.
Напр, в идеально сбалансированном дереве из 1023 узлов время доступа в худшем случае будет равно 10 единицам времени, в среднем:
единицам
времени.
А в вырожденном дереве из 1023 узлов потребуется в худшем случае 1023 единицы времени, в среднем - 512 единиц времени.
Поэтому при работе с деревьями поиска больших размеров крайне желательно, чтобы они были близки к сбалансированным. Приведение уже существующего дерева к идеально сбалансированному - процесс сложный. Проще балансировать дерево в процессе его роста, т.е. после включения каждого узла.
Однако требование идеальной сбалансированности делает и этот процесс достаточно сложным, способным затрагивать все узлы дерева.
10. Алгоритмы быстрой сортировки
Задачей сортировки является преобразование исходной последовательности в последовательность, содержащую те же записи, но в порядке возрастания (или убывания) значений ключа.
Сортировка включением
Алгоритм. Пусть имеется массив ключей a[1], a[2], ..., a[n]. Для каждого элемента массива, начиная со второго, производится сравнение с элементами с меньшим индексом (элемент a[i] последовательно сравнивается с элементами a[i-1], a[i-2] ...) и до тех пор, пока для очередного элемента a[j] выполняется соотношение a[j]>a[i], a[i] и a[j] меняются местами. Если удается встретить такой элемент a[j], что a[j]<=a[i], или если достигнута нижняя граница массива, производится переход к обработке элемента a[i+1] (пока не будет достигнута верхняя граница массива).
Можно сократить число сравнений, применяемых в методе простых включений, если воспользоваться тем фактом, что при обработке элемента a[i] массива элементы a[1], a[2], ..., a[i-1] уже упорядочены, и воспользоваться для поиска элемента, с которым должна быть произведена перестановка, методом двоичного деления (метод бинарной вставки). Для этого ищется элемент, находящийся в середине отмеченной последовательности, и сравнивается с элементом a[i]. После чего производится вставка элемента или в левую часть последовательности или в правую.
Дальнейшим развитием метода сортировки с включениями является сортировка методом Шелла, называемая по-другому сортировкой включениями с уменьшающимся расстоянием. Для массива с 2n элементами алгоритм работает следующим образом. На первой фазе производится сортировка включением всех пар элементов массива, расстояние между которыми есть 2(n-1). На второй фазе производится сортировка включением элементов полученного массива, расстояние между которыми есть 2(n-2). И так далее, пока мы не дойдем до фазы с расстоянием между элементами, равным единице, и не выполним завершающую сортировку с включениями.
Сортировка с помощью дерева (Heapsort)
При использовании метода сортировки с помощью дерева явно строится двоичное дерево сравнения ключей. Построение дерева начинается с листьев, которые содержат все элементы массива. Из каждой соседней пары выбирается наименьший элемент, и эти элементы образуют следующий (ближе к корню уровень дерева). Из каждой соседней пары выбирается наименьший элемент и т.д., пока не будет построен корень, содержащий наименьший элемент массива.
В итоге имеется наименьшее значение элементов массива. Для того, чтобы получить следующий по величине элемент, спустимся от корня по пути, ведущему к листу с наименьшим значением. В этой листовой вершине проставляется фиктивный ключ с "бесконечно большим" значением, а во все промежуточные узлы, занимавшиеся наименьшим элементом, заносится наименьшее значение из узлов - непосредственных потомков. Процесс продолжается до тех пор, пока все узлы дерева не будут заполнены фиктивными.
На каждом из n шагов, требуемых для сортировки массива, нужно log2n сравнений. Следовательно, всего потребуется nlog2n сравнений, но для представления дерева понадобится 2n-1 дополнительных единиц памяти.
Имеется более совершенный алгоритм, который принято называть пирамидальной сортировкой (Heapsort). Его идея состоит в том, что вместо полного дерева сравнения исходный массив a[1], a[2], ..., a[n] преобразуется в пирамиду, обладающую тем свойством, что для каждого a[i] выполняются условия a[i]<=a[2i] и a[i]<=a[2i+1]. Затем пирамида используется для сортировки.
