- •Министерство образования Российской Федерации
- •Содержание
- •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 Дп, жадный алгоритм или что-то другое?
2.8.3 Анализ времени работы сортировки вычерпыванием через геометрическую интерпретацию
Одним из параметров карманной сортировки является количество поддиапазонов для разделения исходной выборки элементов, подлежащих сортировке (т.е. количество «карманов»). Пусть для сортировки каждого кармана будет использоваться алгоритм, работающий за O(n2). Известно, что площадь правильного n-угольника связана с его периметром через прямую пропорциональность (S ~ P). Если зафиксировать количество сторон (в простейшем случае, n = 3), то пропорциональность может быть выражена через константу, которая несущественна для асимптотических оценок и может быть отброшена. Т.е. S = O(P).
В применяемой геометрической интерпретации размер входа алгоритма сортировки для каждого из карманов будет представляться периметром треугольника, а затраты процессорного времени – его площадью (рис. 2.11, (а)). Если количество карманов будет увеличено вдвое, то затраты процессорного времени будут складываться из затрат на сортировку в каждом из карманов вдвое меньшего размера (рис. 2.11, (б)) и так далее.
Обозначим количество карманов как B, периметр как P, а площадь – как S. Условимся также, что увеличение количества карманов не увеличивает периметр исходной фигуры (ведь размер входа не меняется), при этом площадь (т.е. расход процессорного времени) находится как сумма расходов на каждый карман (см. рис. 2.11).
Рисунок 2.11 – Геометрическая интерпретация затрат процессорного времени при различном количестве карманов сортировки вычерпыванием
(а) Один карман. (б) Два кармана. (в) Четыре кармана. (г) Восемь карманов.
Вычисление затрат процессорного времени на сортировку вычерпыванием при бесконечном количестве карманов сводиться к отысканию . Несложно заметить, что. ОтсюдаS = O(P), или T(n) = O(n), что и было доказано в предыдущем подразделе 2.8.2.
2.9 Сортировка подсчетом
2.9.1 Описание алгоритма
Алгоритм сортировки подсчётом (counting sort) применим, если каждый из п элементов сортируемой последовательности – целое положительное число в известном диапазоне (не превосходящее заранее известного k). Если k = О(п), то алгоритм сортировки подсчётом работает за время О(п).
Идея этого алгоритма заключается в том, чтобы для каждого элемента х предварительно подсчитать, сколько элементов входной последовательности меньше х. Далее х записывается напрямую в выходной массив в соответствии с этим числом (если, скажем, 5 элементов входного массива меньше х, то в выходном массиве х должен быть записан на место номер 6). Если предположить, что в сортируемой последовательности могут присутствовать равные числа, то представленная схема потребует небольшой модификации, позволяющей избежать записи нескольких чисел на одно место.
В приводимом ниже псевдокоде используется вспомогательный массив С[1..k] из k элементов. Входная последовательность записана в массиве А[1..п], отсортированная последовательность записывается в массив В[1..п].
Листинг 2.11 – Алгоритм сортировки подсчетом
Работа алгоритма сортировки подсчётом проиллюстрирована на рис. 2.12. После инициализации (строки 1-2) мы сначала помещаем в C[i] количество элементов массива A, равных i (строки 3-4), а затем, находя частичные суммы последовательности С[1],С[2],...,С[k], – количество элементов, не превосходящих i (строки 6-7). Наконец, в строках 9-11 каждый из элементов массива А помещается на нужное место в массиве В. В самом деле, если все п элементов различны, то в отсортированном массиве число A[j] должно стоять на месте номер C[A[j]], потому что именно столько элементов массива А не превосходят A[j]; если в массиве А встречаются повторения, то после каждой записи числа А[i] в массив В число C[A[j]] уменьшается на единицу (строка 11), так что при следующей встрече с числом, равным A[j], оно будет записано на одну позицию левее.
Рисунок 2.12 – Работа алгоритма сортировки подсчетом
На рисунке 2.12 работа алгоритма Counting-Sort, применённого к массиву A[1..8], состоящему из натуральных чисел, не превосходящих k = 6. (а) Массив А и вспомогательный массив С после выполнения цикла в строках 3-4. (б) Массив С после выполнения цикла в строках 6-7. (в-д) Выходной массив В и вспомогательный массив С после одного, двух и трёх повторений цикла в строках 9-11. Затемненные клетки соответствуют элементам массива, значения которым ещё не присвоены. (е) Массив В после окончания работы алгоритма.