2.4.1 Введение в алгоритм
Как и алгоритм сортировки слиянием, алгоритм пирамидальной сортировки требует времени О(п·log п) для сортировки п объектов, но обходится дополнительной памятью размера О(1) (вместо О(п) для сортировки слиянием). Таким образом, этот алгоритм сочетает преимущества двух ранее рассмотренных алгоритмов – сортировки слиянием и сортировки вставками.
Структура данных, которую использует алгоритм (она называется двоичной кучей) оказывается полезной и в других ситуациях. В частности, на её базе можно эффективно организовать очередь с приоритетами.
Термин «куча» иногда используют в другом смысле (область памяти, где данные размещаются с применением автоматической «сборки мусора» – например, в языках Lisp и C#).
Двоичной кучей (binary heap) называют массив с определёнными свойствами упорядоченности. Чтобы сформулировать эти свойства, будем рассматривать массив как двоичное дерево (рис. 2.3). Каждая вершина дерева соответствует элементу массива. Если вершина имеет индекс i, то её родитель имеет индекс (вершина с индексом 1 является корнем), а её дети – индексы (2i) и (2i + 1). Т.к. куча может не занимать всего массива, и поэтому нужно хранить не только массив А и его длину length[A], но также специальный параметр heap-size[A] (размер кучи), причём heap-size[A] ≤ length[A]. Куча состоит из элементов А[1],...,A[heap-size[A]]. Движение по дереву осуществляется процедурами:
Листинг 2.3 – Процедуры перемещения по дереву (реализация на базе массива)
Рисунок 2.3 – Интерпретации кучи: как дерево (а) или как массив (б)
Элемент А[1] является корнем дерева. В большинстве компьютеров для выполнения процедур Left и Parent можно использовать команды левого и правого сдвига (Left, Parent); Right требует левого сдвига, после которого в младший разряд помещается единица. Элементы, хранящиеся в куче, должны обладать основным свойством кучи (heap property): для каждой вершины i, кроме корня (т.е. при 2 ≤ i ≤ heap-size[A]),
Отсюда следует, что значение потомка не превосходит значения предка. Таким образом, наибольший элемент дерева (или любого поддерева) находится в корневой вершине дерева (этого поддерева).
Высотой (height) вершины дерева называется высота поддерева с корнем в этой вершине (число рёбер в самом длинном пути с началом в этой вершине вниз по дереву к листу). Высота дерева, таким образом, совпадает с высотой его корня. В дереве, составляющем кучу, все уровни (кроме, быть может, последнего) заполнены полностью. Поэтому высота этого дерева равна Θ(log n), где п – число элементов в куче. Время работы основных операций над кучей пропорционально высоте дерева и, следовательно, составляет O(log n). Оставшаяся часть главы посвящена анализу этих операций и применению кучи в задачах сортировки и моделирования очереди с приоритетами. Перечислим основные операции над кучей.
• Процедура Heapify позволяет поддерживать основное свойство («ребенок не больше своего родителя»). Время работы составляет O(log n).
• Процедура Build-Heap строит кучу из исходного (неотсортированного) массива. Время работы O(п).
• Процедура HeapSort сортирует массив, не используя дополнительной памяти. Время работы O(nlog n).
• Процедуры Extract-Max (взятие наибольшего) и Insert (добавление элемента) используются при моделировании очереди с приоритетами на базе кучи. Время работы обеих процедур составляет O(log n).
- Министерство образования Российской Федерации
- Содержание
- 1.2 Скорость роста функций
- 1.3 Анализ алгоритмов; время работы в лучшем, худшем случаях и в среднем
- 1.4 Типы данных, структуры данных и абстрактные типы данных
- 1.5 Динамические множества
- 2 Алгоритмы сортировок
- 2.1 Понятие внутренней и внешней сортировки
- 2.2 Сортировка вставками
- 2.3 Сортировка слиянием
- 2.3.1 Описание алгоритма
- 2.3.2 Анализ времени работы алгоритмов «разделяй и властвуй»
- 2.3.2 Анализ времени работы сортировки слиянием через рекуррентное соотношение
- 2.3.3 Анализ времени работы сортировки слиянием через геометрическую интерпретацию
- 2.4 Пирамидальная сортировка
- 2.4.1 Введение в алгоритм
- 2.4.2 Сохранение основного свойства кучи
- 2.4.3 Построение кучи
- 2.5 Быстрая сортировка
- 2.5.1 Введение в алгоритм
- 2.5.2 Описание
- 2.5.3 Разбиение массива
- 2.5.4 Особенности работы быстрой сортировки
- 2.6 Особенности реализации алгоритмов сортировки; сортировка за линейное время
- 2.6.1 Введение
- 2.6.2 Разрешающее дерево сортировки сравнениями
- 2.7 Цифровая сортировка
- 2.8 Сортировка вычерпыванием
- 2.8.1 Описание алгоритма
- 2.8.2 Вероятностный анализ времени работы сортировки вычерпыванием
- 2.8.3 Анализ времени работы сортировки вычерпыванием через геометрическую интерпретацию
- 2.9 Сортировка подсчетом
- 2.9.1 Описание алгоритма
- 2.9.2 Анализ времени работы
- 3 Элементарные и нелинейные структуры данных
- 3.1 Элементарные структуры: список, стек, очередь, дек
- 3.1.1 Список Линейный однонаправленный список
- Линейный двунаправленный список
- Двунаправленный список с фиктивными элементами
- Циклические списки
- Циклический однонаправленный список
- Циклический двунаправленный список
- 3.1.2 Стек
- 3.1.3 Очередь
- 3.1.3 Дек
- 3.2 Нелинейные структуры данных
- 3.2.1 Представление корневых деревьев в эвм
- Обходы деревьев
- 3.2.2 Двоичные деревья Спецификация двоичных деревьев
- Реализация
- Обходы двоичных деревьев
- 3.2.3 Двоичные деревья поиска Основные операции
- Минимум и максимум
- Следующий и предыдущий элементы
- Добавление и удаление
- Случайные деревья поиска
- Оптимальные деревья поиска
- 4 Хеширование
- 4.1 Введение
- 4.2 Прямая адресация; таблицы с прямой адресацией
- 4.3 Хеш – таблицы; возникновение коллизий и их разрешение
- Разрешение коллизий с помощью цепочек
- Анализ хеширования с цепочками
- 4.4 Способы построения хеш – функций Выбор хорошей хеш-функции
- Ключи как натуральные числа
- Деление с остатком
- Умножение
- Универсальное хеширование
- 4.5 Открытая адресация; способы вычисления последовательности испробованных мест: линейная последовательность проб, квадратичная последовательность проб, двойное хеширование
- Линейная последовательность проб
- 1 / (1 – )
- 5 Основные принципы разработки алгоритмов
- 5.1 Введение в теорию графов
- 5.1.1 Графы
- 5.1.2 Представление графов
- 5.2 Алгоритмы на графах: поиск в ширину, поиск в глубину
- 5.2.1 Поиск в ширину (волновой алгоритм)
- 5.2.2 Анализ поиска в ширину
- 5.2.3 Деревья поиска в ширину
- 5.2.4 Поиск в глубину
- 5.2.5 Анализ поиска в глубину
- 5.2.6 Свойства поиска в глубину
- 5.2.7 Классификация рёбер
- 5.3 Топологическая сортировка, задача о разбиении графа на сильно связанные компоненты
- 5.3.1 Топологическая сортировка
- 5.3.2 Сильно связные компоненты
- 5.4 Алгоритм построения минимального остовного дерева
- 5.4.1 Остовные деревья минимальной стоимости
- 5.4.2 Построение минимального покрывающего дерева
- 5.4.3 Алгоритмы Крускала и Пpимa
- 5.4.4 Алгоритм Крускала
- 5.4.5 Алгоритм Прима
- 5.5 Задача нахождения кратчайших путей на графах; алгоритм Флойда; алгоритм Дейкстры
- 5.5.1 Нахождение кратчайшего пути
- 5.5.2 Алгоритм Дейкстры
- 5.5.3 Алгоритм Флойда
- 5.6 Поиск с возвратом
- 5.6.1 Введение
- 5.6.2 Переборные алгоритмы
- 5.6.3 Метод ветвей и границ
- 5.6.4 Метод альфа-бета отсечения
- 5.6.5 Локальные и глобальные оптимальные решения
- 5.7 Метод декомпозиции ( «Разделяй и властвуй»)
- 5.7.1 «Ханойские башни»
- 5.8 Жадные алгоритмы и динамическое программирование
- 5.8.1 Задача о выборе заявок
- 5.8.2 Дискретная задача о рюкзаке
- 5.8.3 Непрерывная задача о рюкзаке
- 5.8.4 Числа Фибоначчи
- 5.8.5 Задача триангуляции многоугольника
- 5.8.6 Дп, жадный алгоритм или что-то другое?