Автор: Пользователь скрыл имя, 12 Января 2011 в 10:25, реферат
Единого «истинного» определения понятия «алгоритм» нет.
«Алгоритм -- это конечный набор правил, который определяет последовательность операций для решения конкретного множества задач и обладает пятью важными чертами: конечность, определённость, ввод, вывод, эффективность». (Д. Э. Кнут)
1.Теория алгоритмов и их возникновение 3
2. Модели вычислений 9
3. Операторные методы 12
3. Сравнительные оценки алгоритмов 20
4. Система обозначений в анализе алгоритмов 24
5. Классификация алгоритмов по виду функции трудоёмкости 31
6. Асимптотический анализ функций 34
Введение
Существует два основных варианта хеш-таблиц: с цепочками и открытой адресацией. Хеш-таблица содержит некоторый массив H, элементы которого есть пары (хеш-таблица с открытой адресацией) или списки пар (хеш-таблица с цепочками).
Выполнение операции в хеш-таблице начинается с вычисления хеш-функции от ключа. Получающееся хеш-значение i = hash(key) играет роль индекса в массиве H. Затем выполняемая операция (добавление, удаление или поиск) перенаправляется объекту, который хранится в соответствующей ячейке массива H[i].
Ситуация, когда для различных ключей получается одно и то же хеш-значение, называется коллизией. Такие события не так уж и редки -- например, при вставке в хеш-таблицу размером 365 ячеек всего лишь 23-х элементов вероятность коллизии уже превысит 50 % (если каждый элемент может равновероятно попасть в любую ячейку) -- см. парадокс дней рождения. Поэтому механизм разрешения коллизий -- важная составляющая любой хеш-таблицы.
В некоторых специальных случаях удаётся избежать коллизий вообще. Например, если все ключи элементов известны заранее (или очень редко меняются), то для них можно найти некоторую совершенную хеш-функцию, которая распределит их по ячейкам хеш-таблицы без коллизий. Хеш-таблицы, использующие подобные хеш-функции, не нуждаются в механизме разрешения коллизий, и называются хеш-таблицами с прямой адресацией.
Число хранимых элементов, делённое на размер массива H (число возможных значений хеш-функции), называется коэффициентом заполнения хеш-таблицы (load factor) и является важным параметром, от которого зависит среднее время выполнения операций.
Свойства хеш-таблицы
Важное свойство хеш-таблиц состоит в том, что, при некоторых разумных допущениях, все три операции (поиск, вставка, удаление элементов) в среднем выполняются за время O(1). Но при этом не гарантируется, что время выполнения отдельной операции мало́. Это связано с тем, что при достижении некоторого значения коэффициента заполнения необходимо осуществлять перестройку индекса хеш-таблицы: увеличить значение размера массива H и заново добавить в пустую хеш-таблицу все пары.
Разрешение коллизий
Существует несколько способов разрешения коллизий.
Каждая ячейка массива H является указателем на связный список (цепочку) пар ключ-значение, соответствующих одному и тому же хеш-значению ключа. Коллизии просто приводят к тому, что появляются цепочки длиной более одного элемента.
Операции поиска или удаления элемента требуют просмотра всех элементов соответствующей ему цепочки, чтобы найти в ней элемент с заданным ключом. Для добавления элемента нужно добавить элемент в конец или начало соответствующего списка, и, в случае, если коэффициент заполнения станет слишком велик, увеличить размер массива H и перестроить таблицу.
При предположении, что каждый элемент может попасть в любую позицию таблицы H с равной вероятностью и независимо от того, куда попал любой другой элемент, среднее время работы операции поиска элемента составляет Θ(1 + α), где α -- коэффициент заполнения таблицы.
Последовательность, в которой просматриваются ячейки хеш-таблицы, называется последовательностью проб. В общем случае, она зависит только от ключа элемента, то есть это последовательность h0(x), h1(x), …, hn -- 1(x), где x -- ключ элемента, а hi(x) -- произвольные функции, сопоставляющие каждому ключу ячейку в хеш-таблице. Первый элемент в последовательности, как правило, равен значению некоторой хеш-функции от ключа, а остальные считаются от него одним из приведённых ниже способов. Для успешной работы алгоритмов поиска последовательность проб должна быть такой, чтобы все ячейки хеш-таблицы оказались просмотренными ровно по одному разу.
Алгоритм поиска просматривает ячейки хеш-таблицы в том же самом порядке, что и при вставке, до тех пор, пока не найдется либо элемент с искомым ключом, либо свободная ячейка (что означает отсутствие элемента в хеш-таблице).
Удаление элементов в такой схеме несколько затруднено. Обычно поступают так: заводят булевый флаг для каждой ячейки, помечающий, удален ли элемент в ней или нет. Тогда удаление элемента состоит в установке этого флага для соответствующей ячейки хеш-таблицы, но при этом необходимо модифицировать процедуру поиска существующего элемента так, чтобы она считала удалённые ячейки занятыми, а процедуру добавления -- чтобы она их считала свободными и сбрасывала значение флага при добавлении.
Последовательности проб
Ниже приведены некоторые распространенные типы последовательностей проб. Сразу оговорим, что нумерация элементов последовательности проб и ячеек хеш-таблицы ведётся от нуля, а N -- размер хеш-таблицы (и, как замечено выше, также и длина последовательности проб).
Линейное пробирование: ячейки хеш-таблицы последовательно просматриваются с некоторым фиксированным интервалом k между ячейками (обычно, k = 1), то есть i-й элемент последовательности проб -- это ячейка с номером (hash(x) + ik) mod N. Для того, чтобы все ячейки оказались просмотренными по одному разу, необходимо, чтобы k было взаимно-простым с размером хеш-таблицы.
Квадратичное пробирование: интервал между ячейками с каждым шагом увеличивается на константу. Если размер хеш-таблицы равен степени двойки (N = 2p), то одним из примеров последовательности, при которой каждый элемент будет просмотрен по одному разу, является:
hash(x) mod N, (hash(x) + 1) mod N, (hash(x) + 3) mod N, (hash(x) + 6) mod N, …
Двойное хеширование: интервал между ячейками
фиксирован, как при линейном пробировании,
но, в отличие от него, размер интервала
вычисляется второй, вспомогательной
хеш-функцией, а значит может быть различным
для разных ключей. Значения этой хеш-функции
должны быть ненулевыми и взаимно-простыми
с размером хеш-таблицы, что проще всего
достичь, взяв простое число в качестве размера,
и потребовав, чтобы вспомогательная хеш-функция
принимала значения от 1 до N -- 1.
СРАВНИТЕЛЬНЫЕ
ОЦЕНКИ АЛГОРИТМОВ
При использовании алгоритмов для решения практических задач мы сталкиваемся с проблемой рационального выбора алгоритма решения задачи. Решение проблемы выбора связано с построением системы сравнительных оценок, которая в свою очередь существенно опирается на формальную модель алгоритма.
Будем рассматривать в дальнейшем, придерживаясь определений Поста, применимые к общей проблеме, правильные и финитные алгоритмы, т.е. алгоритмы, дающие 1-решение общей проблемы. В качестве формальной системы будем рассматривать абстрактную машину, включающую процессор с фон - Неймановской архитектурой, поддерживающий адресную память и набор «элементарных» операций соотнесенных с языком высокого уровня.
В целях дальнейшего анализа примем следующие допущения:
каждая команда выполняется не более чем за фиксированное время;
исходные данные алгоритма представляются машинными словами по битов каждое.
Конкретная проблема задается N словами памяти, таким образом, на входе алгоритма:
Отметим, что в ряде случаев, особенно при рассмотрении матричных задач N является мерой длины входа алгоритма, отражающей линейную размерность.
Кроме того, алгоритм может требовать следующих дополнительных ресурсов абстрактной машины:
Sd - память для хранения промежуточных результатов;
Sr - память для организации вычислительного процесса (память, необходимая для реализации рекурсивных вызовов и возвратов).
При решении конкретной проблемы, заданной N словами памяти алгоритм выполняет не более чем конечное количество «элементарных» операций абстрактной машины в силу условия рассмотрения только финитных алгоритмов. В связи с этим введем следующее определение:
Определение
Трудоёмкость алгоритма. Под трудоёмкостью алгоритма для данного конкретного входа - Fa(N), будем понимать количество «элементарных» операций совершаемых алгоритмом для решения конкретной проблемы в данной формальной системе.
Комплексный
анализ алгоритма может быть выполнен
на основе комплексной оценки ресурсов
формальной системы, требуемых алгоритмом
для решения конкретных проблем.
СИСТЕМА
ОБОЗНАЧЕНИЙ В АНАЛИЗЕ АЛГОРИТМОВ
При более детальном анализе трудоемкости алгоритма оказывается, что не всегда количество элементарных операций, выполняемых алгоритмом на одном входе длины N, совпадает с количеством операций на другом входе такой же длины. Это приводит к необходимости введения специальных обозначений, отражающих поведение функции трудоемкости данного алгоритма на входных данных фиксированной длины.
Пусть ДА - множество конкретных проблем данной задачи, заданное в формальной системе. Пусть D = ДА - задание конкретной проблемы и |D| = N. В общем случае существует собственное подмножество множества ДА, включающее все конкретные проблемы, имеющие мощность N:
обозначим это подмножество через DN:
DN = {D= DN,: |D| = N};
обозначим мощность множества DN через
MDN → MDN = |DN |.
Тогда содержательно данный алгоритм, решая различные задачи размерности N, будет выполнять в каком-то случае наибольшее количество операций, а в каком-то случае наименьшее количество операций. Ведем следующие обозначения:
1. Fa(N) - худший случай - наибольшее количество операций, совершаемых алгоритмом. А для решения конкретных проблем размерностью N:
D=DN
Fa(N) = max {Fa (D)} - худший случай на DN
2. Fa(N) - лучший случай - наименьшее количество операций, совершаемых алгоритмом. А для решения конкретных проблем размерностью N:
D=DN
Fa(N) = min {Fa (D)} - лучший случай на DN
3. Fa(N) - средний случай - среднее количество операций, совершаемых алгоритмом. А для решения конкретных проблем размерностью N:
D=DN
Fa(N)
= (1 / MDN)* {Fa (D)}
- средний случай на DN
КЛАССИФИКАЦИЯ
АЛГОРИТМОВ ПО ВИДУ ФУНКЦИИ ТРУДОЁМКОСТИ
Целью анализа трудоёмкости алгоритмов является нахождение оптимального алгоритма для решения данной задачи. В качестве критерия оптимальности алгоритма выбирается трудоемкость алгоритма, понимаемая как количество элементарных операций, которые необходимо выполнить для решения задачи с помощью данного алгоритма. Функцией трудоемкости называется отношение, связывающие входные данные алгоритма с количеством элементарных операций.
Трудоёмкость алгоритмов по-разному зависит от входных данных. Для некоторых алгоритмов трудоемкость зависит только от объема данных, для других алгоритмов -- от значений, данных, в некоторых случаях порядок поступления данных может влиять на трудоемкость.