лабораторная работа №2 - Кузнецкий институт

advertisement
КУЗНЕЦКИЙ ИНСТИТУТ ИНФОРМАЦИОННЫХ И УПРАВЛЕНЧЕСКИХ
ТЕХНОЛОГИЙ
КАФЕДРА ЕН и ТД
ВАЛИУЛЛОВА Н.А.
УЧЕБНОЕ
ПОСОБИЕ
по курсу "Структуры и алгоритмы обработки данных"
Кузнецк 2008
В данном учебном пособии содержатся сведения, необходимые для выполнения
лабораторных работ по изучению структур и алгоритмов обработки данных
выполненных в среде программирования
Borland Delphi 7.0, Borland C++
Builder, Visual C++.
Работы выполняются в рамках дисциплины "Структуры и алгоритмы обработки
данных" и ориентированы на изучение представления и обработки данных.
Приведены описания общих принципов подготовки, выполнения программ в
среде программирования.
Учебное пособие подготовлено на кафедре "Естественно-научных и
технических дисциплин" и предназначены для студентов специальности
230105.
Составители :
Н.А. Валиуллова
Рецензенты :
доктор технических наук, профессор, зав.кафедрой вычислительных систем и
моделирования ПГПУ им.В.Г.Белинского .............................. Горбаченко В.И.
кандидат технических наук, доцент Математическое обеспечение и применение
ЭВМ ПГУ ...........................................................................................Шибанов С.В.
2
ЛАБОРАТОРНАЯ РАБОТА №1............................................................................ 5
Теоретические сведения: ............................................................................................................... 6
Сортировка с помощью прямого обмена ............................................................................... 6
Сортировка с помощью прямого выбора................................................................................ 7
Сортировка с помощью прямого включения .......................................................................... 8
Быстрая сортировка ................................................................................................................. 10
Сортировка Шелла ................................................................................................................... 10
Рост функций. ........................................................................................................................... 13
Рекомендации для выбора алгоритма сортировки................................................................ 17
Пример оформления: ................................................................................................................... 19
Контрольные вопросы: ................................................................................................................ 20
Задание на лабораторную работу: .............................................................................................. 21
ЛАБОРАТОРНАЯ РАБОТА №2.......................................................................... 26
Теоретические сведения: ............................................................................................................. 27
Простое слияние....................................................................................................................... 27
Естественное слияние .............................................................................................................. 28
Многопутевое сбалансированное слияние ............................................................................ 29
Пример оформления: ................................................................................................................... 30
Контрольные вопросы: ................................................................................................................ 31
Задание на лабораторную работу: .............................................................................................. 32
ЛАБОРАТОРНАЯ РАБОТА №3.......................................................................... 37
Теоретические сведения: ............................................................................................................. 37
Деревья произвольного (общего) вида. ................................................................................. 37
Бинарные (двоичные) деревья. ............................................................................................... 38
Представление бинарных деревьев. ....................................................................................... 39
Алгоритмы обхода бинарных деревьев. ................................................................................ 40
Пример оформления: ................................................................................................................... 44
Контрольные вопросы: ................................................................................................................ 46
Задания на лабораторную работу: .............................................................................................. 47
ЛАБОРАТОРНАЯ РАБОТА №4.......................................................................... 49
Теоретические сведения. ............................................................................................................. 49
Деревья цифрового поиска ...................................................................................................... 49
Создание дерева цифрового поиска. ...................................................................................... 51
Поиск в дереве цифрового поиска.......................................................................................... 51
Пример оформления: ................................................................................................................... 53
Контрольные вопросы: ................................................................................................................ 54
Задание на лабораторную работу: .............................................................................................. 55
ЛАБОРАТОРНАЯ РАБОТА №5.......................................................................... 58
Теоретические сведения. ............................................................................................................ 58
Метод перемещения в начало. ................................................................................................ 58
Метод транспозиции. ............................................................................................................... 58
Пример оформления: ................................................................................................................... 60
Контрольные вопросы: ................................................................................................................ 60
Задание на лабораторную работу: .............................................................................................. 61
Лабораторная работа № 6 ..................................................................................... 62
Теоретические сведения .............................................................................................................. 62
3
Общие понятия ............................................................................................................................. 62
Функции хеширования ............................................................................................................ 62
Хеш-функции ............................................................................................................................... 63
Метод деления .......................................................................................................................... 63
Метод середины квадратов ..................................................................................................... 64
Метод свертывания .................................................................................................................. 64
Метод преобразования системы счисления .......................................................................... 64
Метод деления многочленов ................................................................................................... 64
Метод умножения .................................................................................................................... 65
Коллизии ....................................................................................................................................... 65
Метод открытой адресации ..................................................................................................... 65
Метод цепочек .......................................................................................................................... 67
Метод внешних цепочек.......................................................................................................... 67
Внутренние цепочки ................................................................................................................ 68
Контрольные вопросы: ................................................................................................................ 68
Пример оформления: ................................................................................................................... 69
Задания на лабораторную работу: .............................................................................................. 70
Список использованной литературы: .................................................................. 71
4
ЛАБОРАТОРНАЯ РАБОТА №1
ТЕМА: Алгоритмы внутренней сортировки.
ЦЕЛЬ РАБОТЫ: изучение основных методов упорядочивания данных, расположенных в
оперативной
памяти;
определение
сложности
алгоритмов
сортировки;
производительности и применение алгоритмов для различного типа данных.
ЗАДАНИЕ НА ЛАБОРАТОРНУЮ РАБОТУ:
Написать программу, состоящую из следующих пунктов:
1. Сортировка путем вставок;
2. Обменная сортировка;
3. Сортировка посредством выбора;
4. Сортировка методом Шелла;
5. Быстрая сортировка.
6. Характеристики сортировок;
7. Выход.
В пп. 1- 5 продемонстрировать работу соответствующей сортировки с
различными типами данных.
В п.6 для заданного типа данных и количества подсчитать время сортировки,
число сравнений и перестановок ( сдвигов ) для каждого из алгоритмов.
Входные данные: чтение данных осуществляется из файла;
Выбор типа данных:
1. массив записей; ( количество 5, 10, 25)
2. массив чисел ( количество 10, 100, 1000, 10000).
Выходные данные: В пп. 1- 5 результат выводится на экран;
В п. 6 результат записывается в файл и считывается из него на экран в виде
таблицы:
вид
сортировки
количество
элементов
количество
сравнений
количество
перестановок
время
выполнения
Требования к оформлению лабораторной работы.
при запуске лабораторной работы должно быть:
1. текст задания и фамилию исполнителя в отдельном окне;
2. ввод исходных данных в режиме диалога;
5
Теоретические сведения:
Сортировка - это процесс расстановки элементов в некотором порядке.
Сортировка двух записей состоит из сравнения их ключевых полей и
определения, которое из них меньше. После этого записи переставляются так,
что запись с меньшим ключом ставится перед записью с большим ключом.
При рассмотрении алгоритмов сортировки для простоты будем предполагать,
что записи состоят только из одного поля, что не ограничивает область
применения этих алгоритмов.
Методы сортировки делятся на внутренние и внешние.
Внутренние методы предполагают, что сортируемые данные целиком
располагаются в оперативной памяти.
Внешние методы используются для сортировки файлов данных, которые
слишком велики, чтобы полностью поместиться в оперативной памяти.
Сортировка с помощью прямого обмена
Сортировка с помощью прямого обмена (сортировка стандартным
обменом, сортировка методом пузырька) перемещает один элемент массива S в
соответствующую позицию при каждом просмотре. При первом просмотре
каждый элемент S[i] сравнивается с элементом S[i+1] (1 <= i <= n-1) и при
необходимости, если S[i]>S[i+1], меняется с ним местами. В результате
наибольший элемент помещается в последнюю позицию.
При втором
просмотре выполняются те же действия, но уже не для n, а для (n-1) первых
элементов массива. В результате следующий по величине элемент
перемещается в предпоследнюю позицию.
При третьем
просмотре
рассматриваются уже первые (n-2) элемента массива. Таким образом, для
выполнения сортировки требуется максимально (n-1) просмотров. Во время
каждого просмотра необходимо фиксировать наличие обменов. Если при
очередном просмотре обменов не
было,
то массив уже упорядочен,
сортировка заканчивается.
Алгоритм сортировки прямым обменом состоит из следующих шагов.
1. t='Истина'; j=n-1.
2. Если t - 'Ложь', то 'Массив отсортировн'. Закончить.
3. t='Ложь'.
4. i=1.
5. Если s[i]>s[i+1], то t='Истина' и поменять местами s[i] и s[i+1]
6. i=i+1.
7. Если i<=j, то на шаг 5.
8. j=j-1. На шаг 2.
Анализ
6
В приведенном выше алгоритме переменные имеют следующие назначения:
t - признак отсортированности массива (признак окончания сортировки);
j - определяет количество (j+1) сортируемых в данном проходе
элементов;
i - определяет сравниваемые элементы (s[i] и s[i+1]).
Рассматриваемый алгоритм отличается от большинства алгоритмов
сортировки тем, что он "замечает" отсортированность массива. Для этого
используется логическая переменная
(в
рассмотренном алгоритме переменная t), которая принимает значение "Истина", если при очередном
проходе была хотя бы одна перестановка. Если же перестановок не было, то
массив уже отсортирован, и переменная t будет иметь значение "Ложь".
Число сравнений:
минимальное - (n-1),
среднее - ((n2)/2) - (3n/4),
максимальное - n*(n-1)/2.
Число обменов:
минимальное - 0,
среднее - (n2/4),
максимальное - (n2/2).
Следовательно, алгоритм сортировки методом прямого обмена имеет
сложность O(n2).
Сортировка с помощью прямого выбора
Сортировка с помощью прямого выбора включает в себя следующие шаги.
1. Среди элементов массива S[1], ..., S[n] выбрать элемент с наибольшим
значением.
2. Найденный элемент поменять местами с элементом S[n].
3. Выполнить шаги 1 и 2 для оставшихся n-1 элементов, n-2 элементов и
т.д. до тех пор, пока не останется один, самый маленький элемент.
Алгоритм сортировки прямым выбором состоит из следующих шагов.
1.
2.
3.
4.
5.
6.
7.
j=n.
M=S[1]; k=1; i=2.
Если M<S[i], то M=S[i]; k=i.
i=i+1.
Если i<=j, то на шаг 3.
Иначе, поменять местами S[i] и S[k].
j=j-1.
7
8. Если j>1, то на шаг 2.
9. Иначе, "Массив отсортирован".
В приведенном выше алгоритме переменные имеют следующие
назначения:
j - определяет количество сортируемых в данном проходе элементов;
M - максимальный элемент;
k - индекс максимального элемента.
Число сравнений:
среднее - (n2 - n)/2
Число обменов:
минимальное – 3*(n - 1)
среднее – (n - 1)
максимальное – n2/4+3*(n – 1)
Анализ
Алгоритм сортировки прямым выбором "не замечает" отсортированности
массива. Поэтому количество просмотров всегда постоянно и равно (n - 1).
Если сравнивать быстродействие алгоритмов прямого обмена и прямого
выбора, то последний в среднем работает быстрее. Это объясняется тем, что
количество сравнений в обоих алгоритмах одинаково. Среднее количество
перестановок в алгоритме прямого обмена - (n2)/4. Количество перестановок в
алгоритме прямого выбора равно (n - 1), что значительно меньше. Алгоритм
сортировки методом прямого выбора имеет сложность O(n2).
Сортировка с помощью прямого включения
Сортировка с помощью прямого включения (сортировка вставками)
основана на последовательной вставке элементов в уже упорядоченную
последовательность.
Алгоритм сортировки заключается в следующем.
Сначала упорядоченным считается один, первый элемент. Второй элемент либо
меняется местами с первым, либо остается на своем месте. Далее 3-й элемент
включается в нужное место уже упорядоченной последовательности из 2-х
элементов, за ним 4-й и т.д. до n-го. Пусть необходимо вставить i-й (i>=2)
элемент в уже упорядоченную последовательность из i-1 элементов. Элемент
S[i] последовательно сравнивается с каждым элементом S[k] (0<=k<=i-1) и,
либо вставляется на свободное место, если S[i]>=S[k], либо элемент S[k]
сдвигается на одну позицию вправо и процесс выполняется для элемента S[k1]. Весь процесс вставки элемента заканчивается либо когда найден первый
элемент S[k] такой, что S[k]<=S[i], либо достигнута левая граница
упорядоченной последовательности (элемент S[i] меньше всех элементов
8
упорядоченной последовательности). Очевидным улучшением описанного
выше процесса является установка барьера в нулевом элементе массива S
(S[0]=S[i]), что позволит избежать проверки на выход за левую границу
массива.
Алгоритм сортировки прямым включением состоит из следующих
шагов.
1. i=2.
2. S[0]=S[i].
3. j=i-1.
4. Если S[0]>=S[j], то на шаг 7.
5. S[j+1]=S[j].
6. j=j-1. На шаг 4.
7. S[j+1]=S[0].
8. i=i+1. Если i<=n, то на шаг 2.
9. Иначе, "Массив отсортирован".
В приведенном выше алгоритме
назначения:
S[i] - вставляемый элемент;
S[0] - "барьер".
переменные
имеют
следующие
Число сравнений:
минимальное - (n – 1)
среднее - (n2 + n -2)/4
максимальное – (n2 +n -4)/4
Число обменов:
минимальное – 3*(n-1)
среднее – (n2 +9n - 10)/4
максимальное – (n2 +3n -4)/2
Анализ
Алгоритм
сортировки
прямым
включением
"не
замечает"
отсортированности массива. Поэтому количество просмотров всегда постоянно
и равно (n - 1).
Если сравнивать быстродействие алгоритмов прямого
включения и прямого выбора, то первый в среднем работает быстрее. Это
объясняется тем, что при примерно равном количестве
перестановок
количество сравнений в алгоритме сортировки прямым
включением в среднем в два раза меньше. Алгоритм сортировки методом
прямого выбора имеет сложность O(n2).
9
Быстрая сортировка
Если количество элементов в массиве не многим меньше максимального их
значения, то в данном случае наиболее эффективным и по быстродействию, и
по простоте Основные достоинства этого алгоритма состоят в том, что он
точечный (использует лишь небольшой дополнительный стек), в среднем
требует только около N log N операций для того, чтобы отсортировать N
элементов, и имеет экстремально короткий внутренний цикл. Недостатки
алгоритма состоят в том, что он рекурсивен (реализация очень затруднена когда
рекурсия недоступна), в худшем случае он требует N2 операций, кроме того он
очень "хрупок": небольшая ошибка в реализации, которая легко может пройти
незамеченной, может привести к тому, что алгоритм будет работать очень
плохо на некоторых файлах.
Алгоритм реализуется при помощи рекурсивных вызовов, поэтому
зададим процедуру Сортировка(iLo, iHi).
Она реализует следующие шаги:
1. Lo=iLo, Hi=iHi, Mid=A[(Lo+Hi) div 2];
2. Если A[Lo] < Mid, то Lo=Lo+1, на шаг 2
3. Если A[Hi] > Mid, то Hi=Hi-1, на шаг 3
4. Если Lo > Hi, на шаг 8
5. Поменять местами A[Lo] и A[Hi]
6. Lo=Lo+1, Hi=Hi-1
7. Если Lo <= Hi, на шаг 3
8. Если Hi > iLo, Вывов Сортировка(A,iLo,Hi)
9. Если Lo < iHi, Вывов Сортировка(A,Lo,iHi)
10. Возврат (на предыдущий уровень рекурсии)
Анализ
Данный алгоритм является наиболее быстрым из известных и имеет
несколько модификаций. Однако средняя скорость его работы определяется
выражением O(N * lgN).
Сортировка Шелла
Сортировка вставками не относится к категории быстродействующих,
поскольку
единственный вид операции обмена, который она использует,
выполняется над двумя соседними элементами, в связи с чем элемент может
передвигаться вдоль массив; лишь на одно место за один раз. Например, если
10
элемент с наименьшим значением ключа оказывается в конце массива,
потребуется сделать N шагов, чтобы поместить его в надлежащее место.
Сортировка методом Шелла представляет собой простейшее расширение
метода вставок, быстродействие которого выше за счет обеспечения возможности обмена местами элементов, которые находятся далеко один от
другого.
Возникает вопрос: какую последовательность шагов следует использовать? В
общем случае на этот вопрос трудно найти правильный ответ. В литературе
опубликованы результаты исследований различных последовательностей
шагов; некоторые из них хорошо зарекомендовали себя на практике, однако
наилучшую последовательность, по-видимому, отыскать не удалось. В общем
случае на практике используются убывающие последовательности шагов,
близкие к геометрической прогрессии в результате чего число шагов находится
в логарифмической зависимости от размеров файлов. Например, если размер
следующего шага равен примерно половине предыдущего, то для сортировки
файла, состоящего из 1 миллиона элементов, потребуется примерно 20
шагов, если же такое соотношение примерно равно одной четвертой, то
достаточно будет 10 шагов. Использование как можно меньшего числа шагов
— это весьма важное требование.
Практический результат от обнаружения хорошей последовательности шагов,
по-видимому, ограничен повышением быстродействия алгоритма на 25%, в то
время сама проблема представляет собой довольно таки увлекательную
головоломку
Последовательность шагов 1 4 13 40 121 364 093 3280 9841 ... .Она просто
вычисляется (начав с 1, получить значение следующего шага, множив
предыдущее значение на 3 и добавив 1) и обеспечивает реализацию
сравнительно эффективной сортировки даже в случае относительно больших
файлов.
Многие другие последовательности шагов позволяет получить еще более
эффективную сортировку, однако довольно трудно превзойти эффективность
более чем на 20% даже в случае сравнительно больших значений N. Одной из
таких последовательностей является 1 8 23 77 281 1073 193 16577 ..., т.е.
последовательность 4i+1 +3*2i+ для i > 0. Можно доказать, что приведенная
последовательность обеспечивает повышенное быстродействие для самых
трудных случаев сортировки.
С другой стороны, существуют и плохие последовательности шагов: например,
1 2 4 8 16 32 64 128 256 512 1024 2048 ... (первая последовательность
шагов, предложенная Шеллом еще в 1959 г. скорее всего, служит причиной
низкой эффективности сортировки, поскольку элементы на нечетных позициях
не сравниваются с элементами на четных позициях вплоть до последнего
прохода. Этот эффект заметен на файлах с произвольной организацией, и он
становится катастрофическим в наихудших случаях: эффективность метода
резко
снижается
и
время
выполнения
сортировки
становится
пропорциональным квадрату N, если, например, половина элементов файла с
11
меньшими значениями находится в четных позициях, а другая половина
элементов (с большими значениями) — в нечетных позициях.
Свойство 1. Сортировка методом Шелла выполняет менее N(h — l)(k — l)/g
операций сравнения при g-сортировке h- и k-упорядоченного файла при условии,
что h и k взаимно просты.
Свойство 2. Сортировка методом Шелла выполняет менее О (N 3/2) операций
сравнения для последовательности шагов 1 4 13 40 121 364 1093 3280 9841...
Для больших шагов, когда имеются h подфайлов размером N/h, в наихудшем
случае расходы составляют примерно N2/h. При малых шагах из свойства 1
следует, что стоимость составляет приблизительно Nh. Все зависит от того,
насколько успешно удается вписаться в эти границы на каждом шаге. Это
справедливо для каждой относительно простой последовательности,
возрастающей экспоненциально.
Свойство 3. Сортировка методом Шелла выполняет менее О (N 4/3) операций
сравнения для последовательности шагов 1 8 23 77 281 1073 4193 16577...
Последовательности шагов, которые рассматривались до сих пор, эффективны
в силу того, что следующие один за другим элементы последовательности
взаимно просты. Другое семейство последовательностей шагов эффективно
именно благодаря тому, что такие элементы не являются взаимно простыми.
Свойство 4. Сортировка методом Шелла выполняет менее 0(N( logN)2)
операций сравнения для последовательности шагов 1 2 3 4 6 9 8 12 18 27 16 24
36 54 81...
Рассмотрим треугольник, составленный из шагов, в котором каждое число в два
раза больше, чем число выше и правее, и в три раза больше, чем число выше и
Если мы используем эти числа снизу вверх и справа налево как последовательность шагов в рамках сортировки методом Шелла, то каждому шагу х в нижнем
ряду предшествуют значения 2х и Зх, так что каждый подфайл оказывается 2упорядочен и 3-упорядочен, при этом ни один элемент не передвигается
больше, чем на одну позицию в процессе всей сортировки!
Число шагов из треугольника, которое меньше N по величине, и подавно будет
меньше (Log2 N)2.
12
Эмпирические исследования последовательностей шагов сортировки
методом Шелла.
Сортировка методом Шелла выполняется в несколько раз быстрее по
сравнению с другими элементарными методами сортировки даже в тех случаях,
когда шаги являются степенями 2, в то же время некоторые специальные виды
последовательностей шагов позволяют увеличить ее быстродействие в 5 и
более раз. Три лучших последовательности, приведенные в данной таблице,
существенно различаются по положенным в их основу принципам. Сортировка
методом Шелла вполне пригодна для практических приложений даже в случае
файлов больших размеров. По эффективности она намного превосходит методы
выбора и вставок, равно как и пузырьковую сортировку.
Рост функций.
Для большинства алгоритмов главным параметром (primary parameter)
является N, который оказывает существенное влияние на время их выполнения.
Параметр N может быть степенью полинома, размером файла при сортировке
или поиске, количеством символов в строке или некоторой другой абстрактной
мерой размера рассматриваемой задачи: чаще всего, он прямо пропорционален
величине обрабатываемого набора данных. Когда таких параметров существует
более одного, мы часто сводим анализ к одному параметру, задавая его как
функцию от других параметров или рассматривая одновременно только один
параметр (считая остальные постоянными). Таким образом, мы ограничиваем
себя рассмотрением только одного параметра N без потери общности. Нашей
целью является выражение требований к ресурсам, предъявляемых
разрабатываемыми нами программами (как правило, это время выполнения) в
зависимости от N с использованием максимально простых математических
формул, которые обеспечивают точность расчетов для больших значений
параметров. Алгоритмы, изучаемые нами, обычно имеют время выполнения,
пропорциональное одной из следующих функций:
1
Большинство инструкций большинства программ выполняется один
или максимум несколько раз. Если все инструкции программы обладают этим
свойством, мы говорим, что время выполнения программы постоянно
(constant).
log N
Когда время выполнения программы описывается логарифмической
(logarithmic) зависимостью, программа немного утрачивает быстродействие с
ростом N. Такое время выполнения обычно характерно для программ, которые
сводят крупную задачу к некоторой последовательности задач меньшего
размера, уменьшая на каждом шаге размер задачи на некоторую небольшую
часть. В интересующем нас диапазоне мы будем рассматривать время
выполнения как величину, не превосходящую некоторое большое постоянное
значение. Основание логарифма изменяет это значение, но ненамного:
13
когда N — тысяча, log N равно 3, если основание равно 10, либо примерно 10,
если основание равно 2; когда N равно миллиону, значения log N всего лишь
удвоится. При удвоении N значение logN возрастет на постоянную величину, а
удваивается лишь, когда N увеличится до N2.
N
Когда время выполнения программы линейно (linear), это обычно
означает, что каждый элемент ввода подвергается небольшой обработке. Когда
N равно миллиону, такого же порядка и время выполнения алгоритма. Когда N
удваивается, то же происходит и со временем выполнения. Эта ситуация
оптимальна для алгоритма, который должен обработать N вводов (или произвести N выводов).
NlogN
Время выполнения, пропорциональное .N log N имеет место, когда
алгоритм решает задачу, разбивая ее на подзадачи меньших размеров, решая их
независимо и затем объединяя решения. Из-за отсутствия подходящего
прилагательного ("линерифмический" "linerithmic") мы просто говорим, что
время выполнения такого алгоритма равно N log N. Когда N равно 1 миллион,
N log N возрастает примерно до 20 миллионов. Когда N удваивается, то время
выполнения возрастает более чем вдвое (но не намного более).
N 2
Когда время выполнения алгоритма является квадратичным
(quadratic), он полезен для практического использования применительно к
небольшим задачам. Квадратичное время выполнения обычно характерно для
алгоритмов, которые обрабатывают все элементы данных парами (возможно, в
цикле двойного уровня вложения). Когда N равно одной тысяче, время
выполнения равно одному миллиону. Когда N удваивается, время выполнения
увеличивается в четыре раза.
N3
Аналогичный алгоритм, обрабатывающий элементы данных
тройками (возможно, в цикле тройного уровня вложения), имеет кубическое
(cubic) время выполнения и практически применим лишь для решения малых
задач. Когда N равно 100, время выполнения равно 1 миллиону. Когда N
удваивается, время выполнения увеличивается в восемь раз.
2N
Лишь немногие алгоритмы с экспоненциальным (exponential)
временем выполнения имеют практическое применение, хотя такие алгоритмы
возникают естественным образом при попытках решения задачи "в лоб". Когда
N равно 20, время выполнения равно 1 миллиону.
Когда N удваивается, время выполнения увеличивается в четыре раза!
14
Время выполнения конкретной программы, скорее всего, будет некоторой
константой, умноженной на одно из перечисленных выше выражений (главный
член — leading term) плюс некоторые слагаемые меньшего порядка. Значения
постоянного коэффициента и остальных слагаемых зависят от результатов
анализа и деталей реализации. В грубом приближении коэффициент при
главном члене связан с количеством инструкций во внутреннем цикле: на
любом уровне разработки алгоритма разумно сократить количество таких
инструкций. Для больших N доминирует главный член, для малых N или в
случае тщательно разработанных алгоритмов свой вклад вносят и другие
слагаемые, поэтому сравнение алгоритмов становятся более сложным. В
большинстве случаев мы будем называть время выполнения программ просто
"линейным", "кубическим" и т.д.
В итоге, чтобы уменьшить общее время выполнения программы, мы
минимизируем количество инструкций во внутреннем цикле. Каждую
инструкцию, необходимо подвергнуть исследованию: нужна ли она вообще?
Существует ли более эффективный способ выполнить ту же задачу? Некоторые
программисты считают, что автоматические инструменты, содержащиеся в
современных компиляторах, могут создавать наилучший машинный код;
другие утверждают, что наилучшим способом является написание внутренних
циклов вручную на машинном языке, или ассемблере. Как правило, мы будем
воздерживаться от рассмотрения вопросов оптимизации на таком уровне, хотя
время от времени будем указывать, сколько машинных инструкций требуется
для выполнения определенных операций, чтобы показать, почему на практике
одни алгоритмы могут оказаться быстрее других.
секунды
102
1,7 минуты
4
10
2,8 часа
105
1,1 дня
106
1,6 недели
7
10
3,8 месяца
8
10
3,1 года
109
3,1 десятилетия
1010
3,1 столетия
11
10
никогда
Перевод секунд: Огромная разница между такими числами, как 104 и 108,
становится более очевидной, когда мы применяем их для измерения
промежутков времени, а затем переводим в привычные единицы измерения
времени;(210 примерно равно 103 то этой таблицей можно воспользоваться и
для перевода степеней 2 в привычные единицы времени; н-р 232 секунд
составляет примерно 124 года).
15
Для многих приложений нашим единственным шансом решить крупную
задачу остается использование эффективного алгоритма. В этой таблице
показано минимальное количество времени, необходимое для решения задач
размером 1 миллион и 1 миллиард с использованием линейных алгоритмов,
алгоритмов с зависимостью N log N и квадратичных алгоритмов на
компьютерах с быстродействием 1 миллион, ! миллиард и 1 триллион операций
в секунду. Быстрый алгоритм помогает существенно ускорить решение задачи
на медленной машине, однако быстрая машина не сможет выручить, когда
используется медленный алгоритм.
Таблица 2.2 Значения часто встречающихся функций
Операций
секунду
в
Размер задач 1 миллион
N
N log N
Размер задачи 1 миллиард
N
2
N log N N2
N
106
секунд
секунд
недель
часов
часов
никогда
109
мгновенно
мгновенно
часов
секунд
секунд
десятилетий
1012
мгновенно
мгновенно
секунд
мгновенно
мгновенно
недель
В этой таблице сравниваются значения, принимаемые рядом функций, с
которыми нам придется часто сталкиваться при анализе алгоритмов. Очевидно,
доминирующей является квадратичная функция, особенно на больших
значениях N, а на малых значениях N различие между функциями оказываются
не такими, как можно было бы ожидать. Например, N3/2 больше, чем N lg2 N, на
очень больших значениях N, однако на небольших N наблюдается обратная
картина. Точное время выполнения алгоритма может быть выражено в виде
линейной комбинации этих функций. Мы можем легко отделить быстрые
алгоритмы от медленных из-за огромной разницы, например, междуlg N и N
или N и N2, тем не менее, различия между двумя быстрыми алгоритмами может
потребовать более тщательных исследований.
lg N
3
7
10
13
17
20
√N
3
10
32
100
316
1000
N
10
100
1000
10000
100000
1000000
N lg N
33
664
9966
132877
1990964
19931569
N (lg N)2
110
4414
99317
1765633
27588016
397267426
N3/2
32
1000
31623
100000
31622777
1000000000
N2
100
10000
1000000
100000000
10000000000
1000000000000
При анализе алгоритмов можно воспользоваться еще несколькими
функциями. Например, алгоритм с N2 входными данными, имеющий время
выполнения N 3, лучше рассматривать как алгоритм с зависимостью N3/2. Кроме
того, алгоритмы, допускающие разбиение на две подзадачи, имеют время
выполнения, пропорциональное N log2 N Из табл. 2.2 очевидно, что обе эти
функции ближе к N log N, нежели к N 2.
16
Логарифмическая функция играет особую роль при разработке и анализе
алгоритмов, поэтому ее стоит рассмотреть подробнее. Поскольку нам часто
приходится давать оценку аналитическим результатам, в которых опущен
постоянный множитель, мы будем пользоваться записью "logN", опуская
основание. Изменение основания логарифма с одной константы на другую
меняет значение логарифма лишь на постоянный множитель, однако в
определенных контекстах мы используем конкретные значения оснований
логарифмов. В математике настолько важным является понятие натуральный
логарифм (natural logarithm) с основанием е = 2.71828..., что широкое
распространение получило следующее сокращение: log e N = In N. В
вычислительной технике очень важен двоичный логарифм (binary logarithm)
(т.е. по основанию 2), поэтому используется сокращение log 2 N = Ig N.
Иногда нам приходится вычислять логарифмы, особенно в отношении
больших чисел. Например, lg lg 2256 = lg 256 = 8. Из этого примера должно быть
понятно, что в большинстве практических случаев lg IgN рассматривается как
константа, поскольку значение этого выражения достаточно мало даже для
очень больших N.
Рекомендации для выбора алгоритма сортировки
Если сортируется небольшой объем данных (N < 100), то рекомендуется
выбирать простой метод сортировки, так как сложные алгоритмы занимают
больший размер кода и не эффективны при малом количестве сортируемых
элементов.
 Если сортируются элементы большого размера, то рекомендуется
использовать специальные таблицы с помощью которых осуществляется
доступ к самим элементам (например, это могут быть указатели на элементы
или их порядковые номера), причем ключ по которому сортируются данные
может входить или не входить в данные такой таблицы. После сортировки
таблицы можно или переставить исходные данные по таблице, или оставить все
как есть и осуществлять дальнейший доступ к данным по уже отсортированной
таблице.
 Если сортируются данные в файле, то необходимо учитывать, что большая
часть времени будет тратиться на чтение, запись элемента и перемещение по
файлу. В такой ситуации методы вставок являются не эффективными, так как
требуют большое число перестановок. (Кстати, при внутренней сортировке
время сравнения и перестановки двух элементов практически одинаковое.) Так
же возможно считывать небольшие участки данных в память, там их
сортировать и записывать обратно в память, после чего файл будет уже
частично отсортирован и останется довести дело до конца каким-либо методом,
предпочитающим частично отсортированные данные.
 Если используются структуры данных, отличные организацией доступа от
массива, то необходимо выбирать метод сортировки наиболее подходящий для
данной структуры. Например, если сортируется связный список, то для него
будет эффективен метод вставок. Надо преобразовать соответствующий
алгоритм таким образом, чтобы вначале находилось место для вставки

17
очередного элемента, а затем уже вставлять его (в наших примерах на базе
массива приходилось многократно переставлять элементы, что на самом деле
не эффективно).
 Рекомендуется выбирать алгоритм сортировки с учетом предполагаемого
входного состояния данных (является таблица частично отсортированной,
отсортированной в обратном порядке и т.д.) и рекомендаций приведенных
почти к каждому алгоритму.
 Если после сортировки надо получить новую таблицу содержащую
отсортированные данные (имеется ввиду, что в памяти хранится две таблица:
исходная и отсортированная), то неплохие результаты могут дать алгоритмы
основанные на выборках элементов.
18
Пример оформления:
Рис.1 Окно выбора типа и способа сортировки
Рис. 2. Результат и характеристики сортировки
19
Рис. 3. Таблица характеристик
Контрольные вопросы:
1.
2.
3.
4.
5.
Какова суть алгоритма каждой сортировки?
Анализ каждого алгоритма?
Какой алгоритм наиболее эффективен?
От каких параметров зависит время выполнения сортировки?
Какой функции пропорционально время?
20
Задание на лабораторную работу:
ВАРИАНТ 1.
1. Описать структуру с именем STUDENT, содержащую следующие поля:
 фамилия и инициалы;
 номер группы;
 успеваемость (массив из 5 элементов)
сортировка по номеру группы.
2. Массив чисел в интервале [-20, 50].
ВАРИАНТ 2.
1.Описать структуру с именем AEROFLOT, содержащую следующие поля:
 название пункта назначения;
 номер рейса;
 тип самолета.
сортировка по номеру рейса
2.Массив чисел в интервале [-50, 50].
ВАРИАНТ 3.
1.Описать структуру с именем WORKER, содержащую следующие поля:
 фамилия и инициалы работника;
 название занимаемой должности;
 год поступления на работу.
сортировка по году поступления на работу
2.Массив чисел в интервале [-120, 50].
ВАРИАНТ 4.
1.Описать структуру с именем TRAIN, содержащую следующие поля:
 название пункта назначения;
 номер поезда;
 время отправления.
сортировка по номеру поезда
2.Массив чисел в интервале [-5, 100].
ВАРИАНТ 5.
1.Описать структуру с именем MARSH, содержащую следующие поля:
21
 название начального пункта маршрута;
 название конечного пункта маршрута;
 номер маршрута.
сортировка по номеру маршрута
2.Массив чисел в интервале [-10, 25].
ВАРИАНТ 6.
1.Описать структуру с именем NOTE, содержащую следующие поля:
 фамилия и имя;
 номер телефона;
 дата рождения (массив из трех чисел)
сортировка по номеру телефона
2.Массив чисел в интервале [-10, 40].
ВАРИАНТ 7.
1.Описать структуру с именем ZNAK, содержащую следующие поля:
 фамилия и имя;
 знак Зодиака;
 дата рождения (массив из трех чисел)
сортировка по дате рождения.
2.Массив чисел в интервале [-40, 50].
ВАРИАНТ 8.
1.Описать структуру с именем PRICE содержащую следующие поля:
 название товара;
 название магазина, в котором продается товар;
 стоимость товара в рублях.
сортировка по стоимости товара.
2.Массив чисел в интервале [-20, 100].
ВАРИАНТ 9.
1.Описать структуру с именем ORDER, содержащую следующие поля:
 расчетный счет плательщика;
 расчетный счет получателя;
 перечисляемая сумма в рублях.
сортировка по перечисляемой сумме.
2.Массив чисел в интервале [-20, 10].
22
ВАРИАНТ 10.
1.Описать структуру с именем Tovar, содержащую следующие поля:
 код товара;
 наименование товара;
 цена товара;
сортировка по цене товара.
2.Массив чисел в интервале [-50, 50].
ВАРИАНТ 11.
1.Описать структуру с именем Baza, содержащую следующие поля:
 личный номер ученика;
 фамилия;
 год рождения
 адрес
сортировка по году рождения.
2.Массив чисел в интервале [-20, 50].
ВАРИАНТ 12.
1.Описать структуру с именем Systema, содержащую следующие поля:
 номер планеты по удалению от Солнца;
 название планеты;
 диаметр;
сортировка по диаметру.
2.Массив чисел в интервале [-30, 30].
ВАРИАНТ 13.
1.Описать структуру с именем Systema, содержащую следующие поля:
 название планеты;
 объем;
 удаленность от Земли
сортировка по объему.
2.Массив чисел в интервале [-35, 12].
ВАРИАНТ 14.
1.Описать структуру с именем Sport, содержащую следующие поля:
 название вида;
 фамилия рекордсмена;
23
 дата установление рекорда
сортировка дате установления рекорда.
2.Массив чисел в интервале [-100, 50].
ВАРИАНТ 15.
1.Описать структуру с именем Rasp, содержащую следующие поля:
 направление поезда;
 время отправления поезда;
 общая протяженность пути;
сортировка по протяженности пути.
2.Массив чисел в интервале [-100, 100].
ВАРИАНТ 16.
1.Описать структуру с именем Post, содержащую следующие поля:
 фамилия и инициалы;
 стоимость подписки;
 название газеты или журнала;
сортировка по стоимости .
2.Массив чисел в интервале [-65, 15].
ВАРИАНТ 17.
1.Описать структуру с именем Boln, содержащую следующие поля:
 фамилия и инициалы;
 возраст больного;
 адрес;
сортировка по возрасту.
2.Массив чисел в интервале [-60, 20].
ВАРИАНТ 18.
1.Описать структуру с именем Boln, содержащую следующие поля:
 фамилия и инициалы;
 дата поступления;
 диагноз;
сортировка по дате поступления.
2.Массив чисел в интервале [-40, 40].
ВАРИАНТ 19.
24
1.Описать структуру с именем Doc, содержащую следующие поля:
 номер строки документа;
 текст строки;
 количество символов;
сортировка по количеству символов.
2.Массив чисел в интервале [-20, 50].
ВАРИАНТ 20.
1.Описать структуру с именем Katalog, содержащую следующие поля:
 фамилия и инициалы автора книги;
 год издания;
 название книги;
 количество страниц;
сортировка по количеству страниц.
2.Массив чисел в интервале [-5, 10].
25
ЛАБОРАТОРНАЯ РАБОТА №2
ТЕМА: Алгоритмы внешней сортировки.
ЦЕЛЬ РАБОТЫ: изучение основных методов упорядочивания данных, расположенных во
внешней памяти; определение сложности алгоритмов сортировки; производительности и
применение алгоритмов сортировки последовательностей.
ЗАДАНИЕ НА ЛАБОРАТОРНУЮ РАБОТУ:
Написать программу, состоящую из следующих пунктов:
1. Прямое слияние;
2. Естественное слияние;
3. Сбалансированное двухпоточное слияние;
4. Характеристики сортировок;
5. Выход.
В пп. 1- 3 продемонстрировать работу соответствующей сортировки с
различными типами данных.
В п.4 для заданного типа данных и количества подсчитать время сортировки.
Входные данные: чтение данных осуществляется из файла;
Выбор типа данных:
1. массив записей; ( количество 10, 25)
2. массив чисел ( количество 1000, 10000).
Выходные данные: В пп. 1- 3 результат выводится на экран;
В п. 4 результат записывается в файл и считывается из
него на экран в виде таблицы:
вид
сортировки
количество
элементов
тип
данных
время
выполнения
Время выполнения 1 месяц со дня начала занятий.
Требования к оформлению лабораторной работы.
при запуске лабораторной работы должно быть:
1. текст задания и фамилию исполнителя в отдельном окне;
2. ввод исходных данных в режиме диалога;
3. возможность повторного тестирования без выхода в ОС;
4. основной алгоритм, оформленный в виде процедуры:
 создание «окна» произвольного размера;
 проверки корректности ввода целых, действительных и символьных
данных;
 проверки существования файла.
26
Теоретические сведения:
Внешние сортировки, как правило, применяются для упорядочения большого
количества элементов, расположенных на внешних носителях. При этом доступ
к элементам осуществляется последовательно.
Большинство алгоритмов внешних сортировок используют слияние.
Слияние - объединение двух или более последовательностей в одну,
упорядоченную некоторым образом, с помощью повторяющегося выбора из
доступных в данный момент элементов.
Простое слияние
Рассмотрим двухфазную сортировку простым слиянием.
Пусть дана некоторая последовательность A. Для работы алгоритма
потребуются 2 вспомогательные последовательности B и C.
Фаза 1, проход 1 – по 1 элементу
А: 7 15
2
3
10
4
9
12
11
5
1
В: 7 2
10
9
11
1
С: 15 3
4
12
5
Фаза 2, проход 1
А: 7 15
2
3
4
10
9
12
5
11
1
Фаза 1, проход 2– по 2 элемента
А: 7 15
2
3
4
10
9
12
5
11
1
В: 7 15
4
10
5
11
С: 2 3
9
12
1
Фаза 2, проход 2
А: 2 3
7
15
4
9
10
12
1
5
11
Суть алгоритма заключается в чередующемся выполнении двух его фаз: фазы
распределения и фазы слияния элементов. В первой фазе элементы
"распределяются" определённым образом из последовательности A в
последовательности B и C. Во второй фазе элементы "сливаются" из
последовательностей B и C в последовательность A.
В результате каждого такого прохода, состоящего из двух фаз,
упорядоченность последовательности A будет возрастать: в результате первого
прохода будет упорядочена каждая пара элементов, в результате второго
прохода будет упорядочена каждая четвёрка элементов и т.д. Работа алгоритма
заканчивается тогда, когда последовательность A будет упорядочена
полностью.
Число проходов, необходимых для упорядочения последовательности,
логарифмически зависит от количества элементов. Например, для
упорядочения 1.000 элементов потребуется 10 проходов, для упорядочения
1.000.000 элементов потребуется около 20 проходов, для 1.000.000.000
элементов - около 30 проходов и т.д.
27
Анализ сортировки с помощью слияния. Поскольку на каждом проходе р
удваивается и сортировка заканчивается при р >= n,то всего требуется [log n]
проходов. На каждом проходе по определению копируются по одному разу все
п элементов. Поэтому общее число пересылок
M=n*[log n ]
Число сравнений ключей С даже меньше М, поскольку при копировании
остатков никаких сравнений не производится. Однако поскольку сортировки
слиянием обычно употребляются в ситуациях, где приходится пользоваться
внешними запоминающими устройствами, то затраты на операции пересылки
на несколько порядков превышают затраты на сравнения. Поэтому детальный
анализ числа сравнений особого практического интереса не представляет.
Алгоритм сортировки слиянием выдерживает сравнение даже с
усовершенствованными методами, разбиравшимися ранее. Однако, хотя здесь
относительно высоки затраты на работу с индексами, самым существенным
недостатком является необходимость работать с памятью размером 2п.
Поэтому сортировка слиянием для массивов, т. е. для данных, размещаемых в
оперативной памяти, используется редко.
Естественное слияние
Сортировка естественным слиянием является другим усовершенствованием
сортировки простым слиянием. В ней вводится понятие серии элементов как
последовательности элементов, в которой каждый последующий элемент
больше (меньше) предыдущего.
Фаза 1, проход 1 – распределение серий
А: 7 15
2
3
10
4
9
12
11
5
1
В: 7 15
4
9
12
5
С: 2 3
10
11
1
Фаза 2, проход 1 – слияние
А: 2 3
7
10
11
15
1
4
5
12
5
Фаза 1, проход 2 – распределение серий
В: 2 3
7
10
11
15
5
С: 1 4
9
12
Фаза 2, проход 2– слияние
А: 1 2
3
4
7
9
10
11
12
15
5
В сортировке простым слиянием серии составлялись без учёта первоначального
расположения элементов в исходной последовательности. Сначала длина серий
была равна 1, затем 2, 4 и т.д. Естественное слияние учитывает первоначальное
расположение элементов в последовательности. В результате этого удаётся
уменьшить
число
проходов,
необходимых
для
упорядочения
последовательности. В остальном же сортировка естественным слиянием
аналогична простому слиянию: серии элементов из последовательности A
распределяются поочерёдно в последовательности B и C. Затем элементы
28
"сливаются" обратно в последовательность A, образуя при этом серии большей
длины, чем первоначально, и т.д.
Многопутевое сбалансированное слияние
В предыдущих алгоритмах внешних сортировок распределение элементов
происходило в две последовательности. Во многопутевом слиянии число таких
последовательностей (путей) может быть любым целым числом n  2. Чем
больше путей используется в сортировке, тем меньше проходов понадобится
для
полного
упорядочения
последовательности.
Многопутевое
сбалансированное слияние использует серии естественной длины, и каждый
проход состоит из одной фазы. Рассмотрим работу алгоритма на примере.
Число путей равно 3. Предварительный проход 1 – распределение серий
S1: 7 15
2
3
10
4
9
12
11
5
1
S2 :
S3 :
S4: 7 15
11
S5 : 2 3
10
5
S6 : 4 9
12
1
Проход 2
S1 : 1 2
3
4
7
9
10
12
15
S2 : 1 5
11
Проход 3
S4 : 1 2
3
4
5
7
9
10
11
12
15
29
Пример оформления:
Рис. 1. Окно задания параметров сортировок.
Рис.2. Результат тестирования.
30
Рис. 3. Характеристики тестирования внешних сортировок.
Контрольные вопросы:
1.
2.
3.
4.
5.
Какова суть алгоритма каждой сортировки?
Анализ каждого алгоритма?
Какой алгоритм наиболее эффективен?
От каких параметров зависит время выполнения сортировки?
Какой функции пропорционально время?
31
Задание на лабораторную работу:
ВАРИАНТ 1.
1. Описать структуру с именем STUDENT, содержащую следующие поля:
 фамилия и инициалы;
 номер группы;
 успеваемость (массив из 5 элементов)
 сортировка по номеру группы.
2. Массив чисел в интервале [-20, 50].
ВАРИАНТ 2.
1. Описать структуру с именем AEROFLOT, содержащую следующие поля:
 название пункта назначения;
 номер рейса;
 тип самолета.
 сортировка по номеру рейса
2. Массив чисел в интервале [-50, 50].
ВАРИАНТ 3.
1. Описать структуру с именем WORKER, содержащую следующие поля:
 фамилия и инициалы работника;
 название занимаемой должности;
 год поступления на работу.
сортировка по году поступления на работу
2. Массив чисел в интервале [-120, 50].
ВАРИАНТ 4.
1. Описать структуру с именем TRAIN, содержащую следующие поля:
 название пункта назначения;
 номер поезда;
 время отправления.
сортировка по номеру поезда
2. Массив чисел в интервале [-5, 100].
ВАРИАНТ 5.
1. Описать структуру с именем MARSH, содержащую следующие поля:
 название начального пункта маршрута;
32
 название конечного пункта маршрута;
 номер маршрута.
сортировка по номеру маршрута
2. Массив чисел в интервале [-10, 25].
ВАРИАНТ 6.
1. Описать структуру с именем NOTE, содержащую следующие поля:
 фамилия и имя;
 номер телефона;
 дата рождения (массив из трех чисел)
сортировка по номеру телефона
2. Массив чисел в интервале [-10, 40].
ВАРИАНТ 7.
1. Описать структуру с именем ZNAK, содержащую следующие поля:
 фамилия и имя;
 знак Зодиака;
 дата рождения (массив из трех чисел)
сортировка по дате рождения.
2. Массив чисел в интервале [-40, 50].
ВАРИАНТ 8.
1. Описать структуру с именем PRICE содержащую следующие поля:
 название товара;
 название магазина, в котором продается товар;
 стоимость товара в рублях.
сортировка по стоимости товара.
2. Массив чисел в интервале [-20, 100].
ВАРИАНТ 9.
1. Описать структуру с именем ORDER, содержащую следующие поля:
 расчетный счет плательщика;
 расчетный счет получателя;
 перечисляемая сумма в рублях.
сортировка по перечисляемой сумме.
2. Массив чисел в интервале [-20, 10].
33
ВАРИАНТ 10.
1. Описать структуру с именем Tovar, содержащую следующие поля:
 код товара;
 наименование товара;
 цена товара;
сортировка по цене товара.
2. Массив чисел в интервале [-50, 50].
ВАРИАНТ 11.
1. Описать структуру с именем Baza, содержащую следующие поля:
 личный номер ученика;
 фамилия;
 год рождения
 адрес
сортировка по году рождения.
2. Массив чисел в интервале [-20, 50].
ВАРИАНТ 12.
1. Описать структуру с именем Systema, содержащую следующие поля:
 номер планеты по удалению от Солнца;
 название планеты;
 диаметр;
сортировка по диаметру.
2. Массив чисел в интервале [-30, 30].
ВАРИАНТ 13.
1. Описать структуру с именем Systema, содержащую следующие поля:
 название планеты;
 объем;
 удаленность от Земли
сортировка по объему.
2. Массив чисел в интервале [-35, 12].
34
ВАРИАНТ 14.
1. Описать структуру с именем Sport, содержащую следующие поля:
 название вида;
 фамилия рекордсмена;
 дата установление рекорда
сортировка дате установления рекорда.
2. Массив чисел в интервале [-100, 50].
ВАРИАНТ 15.
1. Описать структуру с именем Rasp, содержащую следующие поля:
 направление поезда;
 время отправления поезда;
 общая протяженность пути;
сортировка по протяженности пути.
2. Массив чисел в интервале [-100, 100].
ВАРИАНТ 16.
1. Описать структуру с именем Post, содержащую следующие поля:
 фамилия и инициалы;
 стоимость подписки;
 название газеты или журнала;
сортировка по стоимости .
2. Массив чисел в интервале [-65, 15].
ВАРИАНТ 17.
1. Описать структуру с именем Boln, содержащую следующие поля:
 фамилия и инициалы;
 возраст больного;
 адрес;
сортировка по возрасту.
2. Массив чисел в интервале [-60, 20].
ВАРИАНТ 18.
1. Описать структуру с именем Boln, содержащую следующие поля:
 фамилия и инициалы;
 дата поступления;
35
 диагноз;
сортировка по дате поступления.
2. Массив чисел в интервале [-40, 40].
ВАРИАНТ 19.
1. Описать структуру с именем Doc, содержащую следующие поля:
 номер строки документа;
 текст строки;
 количество символов;
сортировка по количеству символов.
2. Массив чисел в интервале [-20, 50].
ВАРИАНТ 20.
1. Описать структуру с именем Katalog, содержащую следующие поля:
 фамилия и инициалы автора книги;
 год издания;
 название книги;
 количество страниц;
сортировка по количеству страниц.
2. Массив чисел в интервале [-5, 10].
36
ЛАБОРАТОРНАЯ РАБОТА №3
ТЕМА: Иерархические структуры данных..
ЦЕЛЬ РАБОТЫ: научится работать с иерархическими структурами данных.
Теоретические сведения:
ДЕРЕВЬЯ
Деревья произвольного (общего) вида.
Нелинейные структуры данных отражают более сложные отношения порядка
между объектами, чем отношения следования.
Наиболее важным видом нелинейных структур данных является деревья. Они
выражают отношения: предок, потомок, брат, и т.д.
Формально дерево (tree) определяется как конечное множество Т одного или
более узлов со следующими свойствами:
1. существует один выделенный узел, а именно – корень (root) данного
дерева Т;
2. остальные узлы (за исключением корня) распределены среди m ≥ 0
непересекающихся множеств Т1, …. , Тm называются поддервьями
(subtrees) данного корня.
Как видите, это определение является рекурсивным: дерево определено на
основе понятия дерева. Рекурсивный характер деревьев можно наблюдать и в
природе, например почки молодых деревьев растут и со временем
превращаются в ветви ( поддеревья ), на которых снова появляются почки,
которые также растут и со временем превращаются в ветви (поддеревья), и т.д.
Из этого определения следует, что каждый узел дерева является корнем
некоторого поддерева данного дерева. Количество поддеревьев узла называется
степенью (degree) этого узла. Узел со степенью нуль называется концевым
узлом (terminal node) или листом (leaf). Неконцевой узел называется узлом
ветвления (branch node). Уровень (level) узла по отношению к дереву T
определяется рекурсивно следующим образом. Уровень корня дерева Т равен
нулю, а уровень любого другого узла на единицу выше, чем уровень корня
ближайшего поддерева дерева Т, содержащего данный узел.
G
D
B
E
C
A
G
Рис.1. Дерево 1.
F
D
Рис.1. Дерево 2.
F
E
C
B
A
37
1.
2.
3.
4.
Если не считать различными два дерева, которые отличаются только
относительным порядком поддеревьев узлов, то дерево называется
ориентированным (oriented), поскольку при этом имеет значение только
относительная ориентация узлов, А не их порядок. Сама природа
представления данных в компьютере определяет неявный порядок любого
дерева, поэтому в большинстве случаев упорядоченные деревья представляют
больший интерес. Далее будем неявно предполагать, что все рассматриваемые
деревья являются упорядоченными, если явно не указанно обратное.
Соответственно деревья на рис. 1 и 2 в общем случае рассматриваются как
разные, хотя как ориентированные деревья они совершенно одинаковы.
Лес (forest)- это множество (обычно упорядоченное), не содержащее ни одного
непересекающегося дерева или содержащее несколько непересекающихся
деревьев. Тогда еще одна формулировка п. (b) в данном выше определении
дерева могла бы выглядеть так: узлы дерева при условии исключении корня
образуют лес.
Основные свойства дерева:
корень не имеет предков
каждый узел за исключением корня, имеет единственного предка
каждый узел связан с корнем единственным путем, т.е. в дереве нет
замкнутых циклов
если относительный порядок следующих узлов имеет значение, деревья
называются упорядоченными
Бинарные (двоичные) деревья.
Важное значение имеют упорядоченные деревья второй степени – бинарные.
Бинарным деревом называется конечное множество узлов, которые или пусты
или состоят из 2-х непересекающихся подмножеств: левым и правым
поддеревьями и корнем.
Максимальное число узлов в бинарном дереве высотой h составляет :
N2 = 2h – 1
Максимальное число узлов в бинарном дереве на узле i :
Ni = 2i – 1
Высотой полного бинарного, созданного из n узлов определяется как нижняя
граница логарифма из числа узлов +1:
H = Log 2 n  1
38
Представление бинарных деревьев.
1.
В памяти с последовательной организацией.
Если известен максимальный размер дерева, т.е. его высота и соответствующее
количество узлов в полном дереве, то структуру дерева можно хранить в виде
массива. Корень дерева будет располагаться в элементе с индексом 1. для
каждого коренного узла с индексом k, левое поддерево будет располагаться с
индексом [2*k], а правое [2*k+1].
A B C D E G H
F
I
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
A
B
D
C
E
F
G
H
I
Деревом такой структуры является простота доступа по индексам как от предка
к потомку, так и от потомка к предку. Недостатком является то, что если дерево
не является полным, в массиве, представляющем его, появляется большое
количество пустых элементов. Структура дерева рассчитана на его
определенную высоту. Поэтому дерево не может расти. При удалении узлов из
дерева и соответсвено изменение его структуры, потребуется модификация
массива.
2. Представление бинарного дерева в динамической памяти со связной
организацией.
Элемент хранения узла бинарного дерева состоит из одного или нескольких
полей и 2-х указателей на левое и правое поддерево каждого корневого узла.
39
Type
PTree = ^Tree;
Tree = record
Info : char;
Left, Right : PTree;
End;
Var
Root : PTree;
root
A
B
D
C
E
F
G
H
I
Root = nil – дерево пустое.
Дерево приведенного вида строится начиная с корня с помощью
последовательного включения узлов либо в левое, либо в правое поддерево
корневого узла.
Алгоритмы обхода бинарных деревьев.
Обход – алгоритм обработки, при котором узел дерева обрабатывается
единственный раз одинаковым образом в определенным порядке.
Обход дерева заключается в поэтапном разбиении структуры дерева на корень,
левое и правое поддеревья. И в применении к ним алгоритма обработки узлов
до тех пор пока в процессе разбиения не будет получено пустое поддерево.
Существуют три принципа упорядочивания узлов, которые соответствуют
рекурсивной природе дерева.
Существуют левосторонние и симметричные к ним правосторонние алгоритмы.
Левосторонние алгоритмы:
1) Низходящий (прямой) обход к – л – п(корень левое правое)
a) Обработать корневой узел
b) В низходящем порядке обойти левое поддерево корневого узла
c) В низходящей порядке обойти правое поддерево коневого узла
2) Восходящий обход л – п – к
a) Обойти в восх. порядке левое поддерево
b) Обойти в восх. порядке правое поддерево корневого узла
c) Обработать корневой узел
40
3) Смешанный (обратный) обход л – к – п
a) В смеш. порядке обойти левое поддерево корневого узла
b) Обработать корневой узел
c) В смеш.порядке обойти правое поддерево корневого узла
Различные алгоритмы обхода бинарного дерева делают различную линейную
расстановку множества информационных полей узлов дерева. При различии
алгоритмов обхода, относительный порядок узлов не изменяется.
Бинарное или двоичное дерево есть конечное множество узлов, которое или
пусто, или состоит из корня и двух непересекающихся бинарных деревьев,
называемых левым и правым поддеревом данного дерева.
Построить двоичное дерево и распечатать его. Использовать три варианта
обхода: префиксный или прямой - корень, левое поддерево, правое;
постфиксный или концевой - левое поддерево, правое, корень; и инфиксный или
обратный - левое поддерево, корень, правое.
Пусть вершины дерева задаются буквами. Признак конца текста - точка.
Пустые поддеревья обозначаются звездочками, то есть задается вид дерева.
Пример вводимого текста - СТУ***ДЕ*Н**Т**. При работе с деревом
используются рекурсивные алгоритмы.
Type uk2=^tree;
tree=record (*тип элемента дерева*)
inf:char;
Itree,rtree:uk2;
end;
var root:uk2;
s:string;
i:integer;
procedure create(var link:root); (*создание дерева*)
var pt:uk2;
begin
i:=i+1;
if s[i]<>'.' Then
if s[i]<>'*' then
begin
new(pt);
pt^.inf:=s[i] ;
link:=pt;
41
create (link^. ltree) ;
create (link^. rtree) ;
end
else
link:=nil;
end ;
procedure prefix( link: uk) ; (*префиксный обход*)
begin
if link<>nil then
begin
writeln (link^. inf) ;
prefix(link^.ltree);
prefix(link^.rtree);
end;
end ;
procedure Infix(link:uk) ; ("инфиксный обход*)
begin
if link<>nil then
begin
prefix (link^.ltree);
writeln(link^ . inf) ;
prefix(link^.rtree);
end;
end ;
procedure Postfix( link:uk) ; (*постфиксный обход*)
begin
if link<>nil then
begin
prefix(link^. ltree) ;
42
prefix(link^..rtree);
writeln (link^. inf) ;
end;
end;
begin
writeln ('задайте строку' ) ;
read(s);
{создание дерева}
i:=0;
create(root);
{дерево создано}
Prefix (root) ; (*обход в префиксной форме*)
Infix (root) ; (* обход в инфиксной форме*)
Postfix (root) ; (*обход в постфиксной форме*)
end.
43
Пример оформления:
Пример 1
Рис.1. Титульный лист
Рис. 2. Окно создания дерева с использованием компонента TreeView
Рис. 3. . Окно создания дерева с использованием рисования
44
Пример 2
Рис. Титульный лист
Рис. 2 Основное окно создания сбалансированного дерева
Рис. 3 Обработка дерева
45
Контрольные вопросы:
1. Понятие дерева общего вида?
2. Что называют степенью узла?
3. Какое дерево называют ориентированным?
4. Свойства деревьев?
5. Алгоритмы обхода деревьев?
46
Задания на лабораторную работу:
1. Дерево называется равновесным, если число узлов у правого и левого
поддеревьев каждой вершины разнится не более, чем на единицу. Построить
равновесное дерево и распечатать его.
2. Записать текст в двоичное дерево. Одно слово от другого отделяется в тексте
пробелом (одним или несколькими).
1.1. заменить все слова «машина» на «снег»;
1.2. заменить все слова «да» на «весна».
3. Используя дерево, распечатать текст, заданный в виде строки, в обратном
порядке.
4. Используя дерево, определить в тексте слово максимальной длины. Одно
слово от другого отделяется в тексте пробелом.
5. Используя дерево, подсчитать количество слов в тексте. Одно слово от
другого отделяется пробелом.
6. Используя дерево, удалить из текста все слова «студент». Одно слово от
другого отделяется пробелом.
7. Используя дерево, определить, встречается ли в тексте слово «зима». Одно
слово от другого отделяется пробелом.
8. Построить дерево. Подсчитать число его вершин.
9. Построить бинарное дерево. Записать в другое бинарное дерево все
повторяющиеся элементы первого дерева.
10. Используя бинарное дерево и различные варианты его обхода,
зашифровать некоторый текст.
11. Удалить из равновесного дерева все буквы «А».
12. Добавить в равновесное дерево заданный элемент, не нарушая
равновесности дерева.
13. Построить равновесное дерево. Если в дереве встречаются две подряд
буквы «О», то вставить между ними букву «В», не нарушая равновесность
дерева.
14. Задать дерево и определить уровни узлов дерева,содержащих букву «а».
15. Глубиной дерева называется максимальная величина уровней его узлов.
Построить дерево и определить его глубину.
16. Создать дерево. Найти в дереве длину (число ветвей) пути от корня до
ближайшей вершины с заданным элементом.
17. Деревом сортировки называется двоичное дерево, построенное по
следующему правилу. Если элемент меньше, чем корень, то он должен
добавляться в левое поддерево, если больше - то в правое. Если в дереве есть
корень с таким же значением, то добавления не происходит. Построить
обычное дерево, элементами которого являются числа. Удалить из дерева
все повторяющиеся элементы.
18. Вершина дерева называется терминальной или листом, если она не
47
ссылается ни на один элемент дерева. Распечатать все терминальные
вершины дерева сортировки.
19. Если вершина дерева не является листом, то она называется
нетерминальной. Построить дерево сортировки и распечатать все его
нетерминальные вершины, большие заданного числа.
20. Построить дерево сортировки. Если в дереве встречаются числа «3», «4»,
«5», то удалить число «4» из дерева.
21. Добавить в дерево сортировки число «5», если его в дереве нет.
22. Построить дерево сортировки и исключить из дерева число «2».
23. Найти минимальный элемент дерева сортировки.
24. Проверить содержит ли дерево сортировки заданный элемент.
48
ЛАБОРАТОРНАЯ РАБОТА №4
ТЕМА: Цифровой поиск.
ЦЕЛЬ РАБОТЫ: изучение методов организации хранения и поиска данных с помощью
дерева цифрового поиска.
Теоретические сведения.
Деревья цифрового поиска
Существует класс задач, которые оперируют с данными, представляющими
собой множество слов некоторого языка. К таким задачам можно отнести
задачи проверки орфографии, задачи перевода текста и т. п.
Одна из основных операций, которая часто используется в подобных задачах –
поиск слова в множестве слов. Эффективность организации такого поиска во
многом является определяющим для всей системы в целом.
Пусть имеется множество слов М. Необходимо определить, принадлежит ли
слово s множеству М.
Поставленную выше задачу можно решить с помощью одного из
рассмотренных нами ранее алгоритмов поиска. Одним из наиболее
эффективных, например является алгоритм бинарного поиска. Однако, вопервых, множество М должно быть упорядоченно, что является существенным
ограничением. Во-вторых, время поиска будет зависеть от размера множества
М, а не от искомого слова s.
Для рассмотренного выше класса задач используют еще один алгоритм поиска
– алгоритм цифрового поиска.
Пусть множество слов М неупорядоченно, т.е. для поиска приемлем только
последовательный поиск. В этом случае время поиска значительно сократится,
если разбить множество М на подмножества МА , МБ …, МЯ, в каждом из
которых хранятся слова на соответствующую букву.
49
Тогда структура хранения будет выглядеть как двухуровневое дерево
следующего вида (рис.1):
Указатель
на голову
дерева
А
Б
В
Я
Рис.1. Двухуровневое дерево.
На первом уровне этого дерева массив указателей, каждый из которых может
быть либо пустым ( указатели ъ, ь, й ), либо содержать адрес соответствующего
подмножества слов, находящегося на втором уровне дерева.
Рассмотренный выше подход можно развить дальше, организовав
трехуровневое дерево, в котором первый уровень – указатели для первой буквы
слова, второй – указатели для второй буквы слова, третий – множество слов,
начинающихся на АА, АБ, … , ЯЯ.
Ясно, что при этом количество элементов в подмножествах МАА, МАБ, … ,МЯЯ
значительно уменьшится, а следовательно, уменьшится и время
последовательного поиска.
Продолжая процесс увеличения уровней дерева, можно прийти к структуре
дерева, в котором каждая буква слова будет располагаться на своем уровне.
Такое дерево называется деревом цифрового поиска или бором.
При такой организации хранения и поиска данных время поиска слова будет
зависеть только от количества букв в этом слове.
50
Создание дерева цифрового поиска.
Рассмотрим процесс формирования дерева цифрового поиска на примере.
Пусть задано множество слов {слово, слон, стул, сто, пять, путь, пятак}.
Построим дерево цифрового поиска (рис.2):
Указатель
на голову
дерева
П
У
С
Я
Т
Л
О
Т
В
А
Ь
Т
Ь
У
Н
Л
О
К
Рис.2. Пример дерева цифрового поиска.
Поиск в дереве цифрового поиска.
Алгоритм поиска по бору достаточно очевиден. Первая буква искомого слова
ищется на первом уровне дерева. Если в соответствующей букве указатель пуст
– поиск неудачен. В противном случае вторая буква слова таким же образом
ищется в элементе дерева на втором уровне по найденному указателю и т.п.
Поиск заканчивается либо когда в очередном узле встретится пустой указатель
(поиск неудачен), либо когда будет найдена последняя буква искомого слова.
При всей очевидности алгоритма поиска в нем есть несколько не всегда
очевидных моментов. Так, если использовать рассмотренный выше алгоритм
формирования бора, то в дереве на рис.2 будет найдено не только слово
«пятак», но и слово «пята», а также слова «пят», «пя», «п» и другие подслова
введенных слов, хотя мы их не вводили.
Для решения этой проблемы необходимо, чтобы каждое заносимое в бор слово
имело символ завершения. Если предположить, что мы рассматриваем только
слова русского языка, записанные большими буквами, то символом завершения
слова может быть буква «а», имеющая следующий за буквой «Я» код.
51
В этом случае каждый узел дерева цифрового поиска будет представлять собой
массив из 34 указателей(33 буквы русского алфавита, 34 – символ завершения
слова). На языке Паскаль такой массив указателей может быть описан
следующим образом:
Mas: array[‘A’..’a’] of <указатель>
что позволит обращаться к каждому указателю по соответствующей букве, не
используя ненужные вычисления.
Очевидно, что при такой организации хранения данных очень расточительно
используется память. Требуемую память можно сократить за счет увеличения
времени выполнения, представляя каждую вершину бора в виде связанного
списка.
Другой подход к использованию деревьев цифрового поиска предполагает, что
только несколько уровней бора используются для поиска первых букв ключа, а
для поиска оставшихся букв используется какая-нибудь другая структура типа
линейного списка или бинарного дерева.
Другими словами, на практике можно использовать цифровой поиск как
промежуточный вариант между рассмотренными нами на рис1,2 структурами.
52
Пример оформления:
Рис.1 Основное окно программы
Рис.2 Построение дерева цифрового поиска
Рис.3 Окно поиска слова в дереве цифрового поиска
53
Контрольные вопросы:
1. Какова структура узла дерева цифрового поиска?
2. Какова структура дерева цифрового поиска?
3. Привести пример формирования дерева цифрового поиска?
4. Привести пример поиска в дереве цифрового поиска?
54
Задание на лабораторную работу:
Написать программу в среде программирования Delphi 7.0, реализующую
алгоритм цифрового поиска. Обязательно должны быть пункты меню:
1. создание пустого дерева цифрового поиска;
2. добавление слова в дерево цифрового поиска;
3. поиск слова в дереве цифрового поиска;
4. выход.
ВАРИАНТ 1.
{вагон, ведро, дом, модель, метроном, развалина, звук, вещь, калач, чебурашка,
автомат, тромб, каракуль, утка, пароход}
ВАРИАНТ 2.
{окно, автобус, автомат, объект, аэробус, плакат, поле, метод, класс,
контрольная, книга, программирование, программист, стиль, яблоко}
ВАРИАНТ 3.
{антон, веревка, валенки, проспект, батон, яйцо, цветок, колонки, пульт, книга,
альбом, папка, каталог, диск, листок}
ВАРИАНТ 4.
{карандаш, ручка, пенал, монитор, подставка, подвал, песок, ручей, каракули,
каска, пенка, пулемет, список, дата, дорога}
ВАРИАНТ 5.
{гранат, география, гиря, автомат, машина, шина, авторучка,
министерство, мастерство, кран, карантин, карандаш, кара, круиз}
мина,
ВАРИАНТ 6.
{пасьянс, паспорт, полка, информация, балет, база, белый, изложение,
изобилие, народ, наследие, немой, необыкновенный, позади, поздний}
ВАРИАНТ 7.
{религия, реплика, репортаж, репутация, реферат, сенсация, сердце, середина,
серия, тавтология, тайна, такт, тактика, танец, таять}
ВАРИАНТ 8.
{удалить, удивить, удар, удача, удивительный, финал, финансы, финиш, флот,
фонд, чувство, чудо, чуждый, чуткий, чистый}
55
ВАРИАНТ 9.
{обновить, обобщить, обозначить, оболочка, образец, партия, пассивный,
патриот, пейзаж, перемена, радость, разведка, развести, развить, раздумье}
ВАРИАНТ 10.
{размер, разрушить, разорвать, разорить разместить, скромный, скрыть,
скудный, слабый, слава, тень, теория, тёплый, терзать. терпеть}
ВАРИАНТ 11.
{территория, тепло, терзать, террор, теснота, убедить, уважать, увеличить,
увлекать, удар, человек, чередовать, чернеть, черта, чертить }
ВАРИАНТ 12.
{авангард, автомат, авторитет, адресат, автономия, бассейн, беда, беречь,
бережливый, беспокойный, грузить, грустить, гуманизм, грызть, груз}
ВАРИАНТ 13.
{даль, дарить, дать, двинуть, девиз, заказ, закон, заложить заметить, закрыть,
игра, идеал, идея, изложить, изобилие}
ВАРИАНТ 14.
{инициатива, инстинкт, импровизация, интеллект, интервал, кадр, камера,
кампания, кандидат, капитан, лабиринт, лавина, лагерь, лазурь, лауреат}
ВАРИАНТ 15.
{логика, любовь, ловкость, лицо, лик, находка, надежда, надежность, наладка,
народ, номер, нрав, обелиск, обида, обзор}
ВАРИАНТ 16.
{обман, обилие, облик, область, оболочка, павильон, пакет, патриарх, перевод,
перепись, периферия, совет, совершенство, совесть, событие}
ВАРИАНТ 17.
{образец, образование, образ, оболочка, общество, находка, наполнить,
напомнить, непостижимый, неуклонный, устав, устойчивый, устройство, устье,
успокоить}
56
ВАРИАНТ 18.
{театр, темперамент, тезис, творчество, текст, конференция, конфликт, концерт,
копать, корень, жажда, жанр, жест, жизнь, жюри}
ВАРИАНТ 19.
{забота,
зависть,
заговор,
задача,
заказ,
инструмент,
интервал,
интернациональный, интерес, интонация, молодость, молчание, монолит,
монолог, монополия}
ВАРИАНТ 20.
{нация, невежа, недостаток, немой, ненависть, образец, образ, оборудование,
оболочка, обсерватория, плотность, плоскость, поверхность, повод, поворот}
57
ЛАБОРАТОРНАЯ РАБОТА №5
ТЕМА: Самоорганизующиеся таблицы
ЦЕЛЬ РАБОТЫ: изучение методов организации
самоорганизующихся таблиц..
и
поиска
данных
с
помощью
Теоретические сведения.
В рассмотренных алгоритмах последовательного поиска предполагалось, что
поиск любого из ключей может потребоваться с равной вероятностью. Однако
часто такое предположение ложно.
Пусть вероятность поиска ключа К1 равна р1,
где
р1 + р2 + … + рn =1.
Очевидно, что число сравнений при поиске будет минимально, если
р1  р2  …  рn,
т.е. когда наиболее часто используемые записи находятся в начале таблице.
Однако в большинстве случаев распределение вероятностей заранее не
известно. В этом случае можно в каждой записи завести счетчик числа
обращений, чтобы на основании показаний счетчиков переупорядочивать
записи. Такая процедура может привести к заметной экономии. Однако не
всегда желательно выделять дополнительную память под счетчики, так как ее
можно использовать более рационально.
Рассмотрим 2 способа организации и поиска данных, в которых положение
записей в таблице может меняться в процессе работы с этой таблицей.
Метод перемещения в начало.
Достаточно давно и эффективно используется следующая простая схема:
найденная запись помещается в начало таблицы.
Такая схема позволяет довольно хорошо упорядочивать записи без
использования вспомогательных полей счетчика. В результате часто
используемые элементы будут располагаться довольно близко к началу.
Метод перемещения в начало наиболее легко реализовать, когда таблица
представлена в виде связного линейного списка.
Метод транспозиции.
Другим методом переупорядочивания таблицы является метод транспозиции,
при котором извлеченная запись меняется местами с записью, которая ей
предшествует.
Показано, что метод транспозиции в конце концов дает более эффективный
поиск, чем метод перемещения в начало таблицы для тех таблиц, в которых
вероятность доступа к некоторой конкретной записи остается постоянной во
времени.
58
Однако метод транспозиции требует большего времени для достижения
максимальной эффективности, чем метод перемещения в начало. Поэтому
может быть рекомендована некоторая смешанная стратегия, при которой
первоначально используется метод перемещения в начало, что позволит быстро
переупорядочить таблицу, а затем используется метод транспозиции для
поддержания данной таблицы в относительном порядке.
Другим преимуществом метода транспозиции является то, что он может быть
одинаково эффективно применим к таблицам, представленным в виде массива
и в виде списка.
59
Пример оформления:
Рис.1 Основное окно
Рис.2 Окно сравнения двух методов.
Контрольные вопросы:
1. Какова особенность переупорядочивания данных с помощью методов
перемещения в начало?
2. Какова особенность переупорядочивания данных с помощью метода
транспозиции?
60
Задание на лабораторную работу:
1. Сформировать связный список из n элементов. Каждый элемент списка
должен иметь следующую структуру:
Ключ Начало интервала Конец интервала Порядковый номер
Где Ключ – ключ поиска; Начало интервала, Конец интервала – промежуток
значений, при попадании в который будет выбран данный ключ;
Порядковый номер – место данного элемента в списке, упорядоченном по
убыванию вероятности (т.е. в идеально организованном списке)
2. Датчиком случайных чисел заполнить первое поле каждого элемента списка.
3. Датчиком случайных чисел определить для каждого ключа интервал
значений (2 и 3 поля). Интервалы определяются следующим образом: пусть
датчик случайных чисел для первого элемента списка выдаст число k, тогда
интервал первого ключа будет равен 1+k. Если для второго элемента датчик
выдаст число t, то интервал второго ключа – k+k+t. Если для третьего
элемента датчик выдаст число s, то интервал третьего ключа – k+t + k+t+s и
т.д. на основе получаемых датчиком значений заполнить четвертое поле для
каждого из элементов списка.
4. Написать процедуры, реализующие метод перемещения в начало, и метод
транспозиций для списка заданной в п.1 структуры.
5. Подавая на вход каждой из процедур, последовательности для поиска из n/2,
n, 2*n, 5*n, 10*n ключей, определять степень оптимальности организации
данных как сумму модулей разности фактического положения каждого
элемента списка и его положения в идеально организованном списке
(значение поля 4).
6. Нарисовать график зависимости степени оптимальности организации
данных от количества элементов поиска для каждого из рассмотренных
методов.
61
Лабораторная работа № 6
ТЕМА: Хеширование.
ЦЕЛЬ РАБОТЫ: изучить основные методы организации таблиц
идентификаторов, получить представление о преимуществах и недостатках,
присущих различным методам организации таблиц идентификаторов..
Теоретические сведения
Общие понятия
В последовательном и бинарном методах поиска время поиска является
функцией от n, где n - количество элементов. Лучший из них, бинарный поиск,
имеет сложность O(log n).
Эффективными методами поиска являются те методы, которые
минимизируют число ненужных сравнений. В идеале хотелось бы иметь
такую организацию данных, при которой вообще не было бы ненужных
сравнений.
Если каждый ключ должен быть извлечен за одно обращение, то положение
записи (ее адрес) должно зависеть только от значения ключа этой записи.
Следовательно, необходим метод преобразования ключа в некоторый адрес в
заданном диапазоне.
Организацию данных в виде таблицы назовем хеш-таблицей, если адрес каждой
записи а этой таблицы определяется как значение некоторой функции h(k),
называемой хеш-функцией. Здесь k — значение ключа записи а.
Если число записей невелико и заранее известно, то можно построить функцию
преобразования заданного множества ключей в различные адреса. Если
возможно, то в последовательные адреса, что выгодно при использовании
виртуальной памяти. Если же число записей велико, то найти такую функцию
оказывается сложно. В случае если число различных значений ключей,
вероятность появления которых отлична от нуля, превышает размер хештаблицы, построение функции оказывается невозможным. В этом случае
приходится отказываться от идеи однозначности и рассматривать хешфункцию как функцию, рассеивающую множество ключей во множестве
адресов Оm — 1.
Отказ от требования взаимно однозначного соответствия между ключом и
адресом означает, что для двух различных ключей k1 k2 значение хешфункции может совпадать: h(k1) = h(k2). Такая ситуация называется коллизией.
Ключи k1 и k2 называются синонимами хеш-функции h, если h(k1) = h(k2).
Для метода хеширования главными задачами являются выбор хеш-функции и
нахождение способа разрешения возникающих коллизий.
Функции хеширования
Процедура преобразования ключа в адрес обычно выполняется в три этапа.
62
1. Если ключ не цифровой, он преобразуется в соответствующее цифровое
представление таким образом, чтобы исключить потерю информации,
содержащейся в ключе. Например, буквы могут переводится в цифровой
код, либо символы представляются в виде строки битов.
2. Ключи в цифровом или битовом представлении затем преобразуются
(функцией хеширования) в совокупность произвольно распределенных
чисел, значения которых имеют тот же порядок, что и значения адресов
основной области памяти. Желательно, чтобы набор ключей был
распределен как можно равномернее в диапазоне допустимых адресов.
3. Полученные числа умножаются на константу, что позволяет разместить их
строго в диапазоне значений адресов основной области памяти. Например,
пусть в результате выполнения этапа 2 получаются четырехзначные числа
(т.е. число от 0 до 9999), а в области памяти выделено 7000 адресов. Тогда
числа следует умножать на 0.7, что позволит получать адреса в интервале от
0 до 6999.
Хеш-функции
При выборе хеш-функции следует учитывать сложность ее вычисления, а также
равномерность распределения значений, которая позволяет не только сократить
число коллизий, но и не допустить скучивания значений в отдельных частях
таблицы.
Для каждого конкретного множества возможных ключей можно изобрести
(подобрать, найти) свою, возможно наилучшую, хеш-функцию распределения
ключей по таблице. Но существуют и универсальные хеш-функции, дающие
хорошие результаты в большинстве случаев. Рассмотрим некоторые из них.
Метод деления
Рассмотрим три основные хеш-функции, используемые на этапе 2 для
преобразования ключа в адрес: метод деления, метод середины квадратов и
метод свертывания ключа. Наиболее распространенная функция хеширования
основывается на методе деления и определяется в виде
H(K) = (K mod m) + 1,
где K - ключ, mod - операция, вычисляющая остаток от деления, m - делитель.
Равномерность распределения получаемых адресов во многом зависит от
выбранного делителя m. Следует избегать четных делителей, так как при этом
четные и нечетные ключи отображаются соответственно в четные и нечетные
адреса. Если множество ключей состоит в основном из четных или в основном
из нечетных ключей, будут возникать многочисленные коллизии.
Как показывают исследования, если m является большим простым числом, то
количество коллизий невелико. Также неплохие результаты дает выбор в
качестве делителя m числа, которое не является простым и не содержит
простых сомножителей, меньших 20.
63
Метод середины квадратов
При хешировании по методу середины квадратов сначала ключ умножается
сам на себя. В качестве адреса выбирается столько цифр из середины
результата, какова требуемая длина адреса.
Рассмотрим вышеизложенное на примере. Пусть дан ключ 234583. При
возведении его в квадрат получаем 55029183889. Если требуется 100 адресов,
то адрес будет равен 91, если необходимо 1000 адресов - 918, если 10000 - 2918
и т.д.
Иногда необходимо получить некратное 10 количество адресов, например
736. В этом случае необходимо взять три средние цифры и умножить на
коэффициент 0.736.
Например 918*0.736 = 676.
Эксперименты с реальными
данными показали, что метод середины
квадратов дает неплохой результат при условии, что ключи не содержат
много левых или правых нулей подряд.
Метод свертывания
В методе свертывания ключ разбивается на части, каждая из которых имеет
длину, равную длине требуемого адреса. Адрес формируется как сумма
этих частей. При этом перенос в старший разряд игнорируется.
Пусть дан ключ 3415768898. Для двух-, трех- и четырехцифрового адреса
получим следующие значения
34+15+76+88+98 = 11;
3+415+768+898 = 084;
34+1576+8898 = 0508.
Метод свертывания используется, как правило, для больших ключей.
Как показывает практика, разбиение справа налево предпочтительнее
разбиения слева направо.
Метод преобразования системы счисления
В основе метода лежит преобразование значения ключа k, выраженного в
системе счисления с основанием р (k = a0 + а1р + a2p2 + ...), в систему
счисления с основанием q (h(k) = a0 + а1q + a2q2 + ...) при условии, что р < q.
Трудоемкость (число операций) этого метода оказывается большей, чем
методов деления или умножения.
Метод деления многочленов
Пусть k, выраженное в двоичной системе счисления, записывается как
k = 2nbn + ... + 2b1 + b0, и пусть размер хеш-таблицы m является степенью
двойки m = 2Р. Представим двоичный ключ k в виде многочлена вида
k(t) = bntn + ... + b1t+ b0. Определим остаток от деления этого многочлена на
постоянный многочлен вида c(t) = tm+cm-1tm-1+…c1t+c0. Этот остаток,
рассматриваемый в двоичной системе счисления, используется в качестве
64
значения хеш-функции h(k). Для вычисления остатка от деления многочленов
используют полиномиальную арифметику по модулю 2. Если в качестве c(t)
выбрать простой неприводимый многочлен, то при условии близких, но не
равных k1 и k2, обязательно будет выполняться условие
h(k1)  h(k2). Многочлен c(t) называется простым неприводимым многочленом, если его нельзя представить в виде произведения c(t) = q(t) x r(t), где q(t)
и r(t) — многочлены, отличные от константы. Эта функция обладает сильным
свойством рассеивания скученностей.
Метод умножения
Представим значение ключа k в виде двоичного числа и примем размер хештаблицы m равным 2 Р. Умножим дробь d на k и возьмем дробную часть числа,
которую обозначим как {k x d}, а в качестве значения хеш-функции используем
p старших разрядов1, т. е. h(k) = m x {kd}, где x — наибольшее целое число,
не превосходящее х. Рекомендуется в качестве значения d
брать иррациональное число, например золотое сечение (sqrt(5) -1)/2. При
d =1/m метод эквивалентен методу деления.
Коллизии
Как уже отмечалось, каждый ключ может быть цифровым (номер зачетной
книжки), алфавитным (ФИО студента) или алфавитно-цифровым (номер
группы). Однако всегда имеется возможность преобразовать ключи в целые
числа, поэтому будем предполагать, что множество ключей состоит из целых
величин.
Любая хорошая функция хеширования должна как можно равномернее
распределять ключи по всему диапазону значений адресов. Однако всегда
существует вероятность того, что найдутся ключи Ki<>Kj такие, что
H(Ki)=H(Kj). Такая ситуация называется коллизией при хешировании.
При использовании метода хеширования необходимо решить две задачи:
выбрать функцию хеширования и метод разрешения коллизий.
Существует два основных метода разрешения коллизий: метод открытой
адресации и метод цепочек.
Метод открытой адресации
а)Добавление ключа
В методе свертывания ключ разбивается на части, каждая из которых имеет
длину, равную длине требуемого адреса. Адрес формируется как сумма
этих частей. При этом перенос в старший разряд игнорируется.
Пусть дан ключ 3415768898. Для двух-, трех- и четырехцифрового адреса
получим следующие значения
34+15+76+88+98 = 11;
3+415+768+898 = 084;
34+1576+8898 = 0508.
65
Метод свертывания используется, как правило, для больших ключей.
Как показывает практика, разбиение справа налево предпочтительнее
разбиения слева направо.
б)Поиск и удаления ключа
Алгоритм поиска ключа состоит в вычислении его хеш-адреса и просмотре
той же последовательности элементов. Либо, при удачном поиске, будет
найден искомый ключ, либо, при поиске неудачном, будет найден пустой
элемент или будут просмотрены все элементы массива.
Если из массива удаляется ключ Ki, то в соответствующий элемент массива
необходимо занести специальный признак удаленного ключа (например,
отрицательное число, если все ключи положительные, или наибольшее
положительное число), т.е. значение, которое не равно ни одному возможному
значению ключа.
При поиске помеченные как удаленные записи рассматриваются как
занятые, а при занесении, как свободные.
в) Пример
Рассмотрим применение метода открытой адресации на примере. Пусть
задан массив S из 11 элементов, хеш-функция H(K) = (K mod 11) + 1 и
последовательность ключей 88, 21, 96, 86, 11, 22, 5, 29, 19.
Результаты заполнения массива методом открытой адресации показаны на
рисунке.
Как видно из рисунка, коллизия возникает при занесении ключей 11, 22 и 19.
1
88
2
11
3
22
4
19
5
6
5
7
8
29
9
96
10
86
11
21
г) Анализ
Разрешение коллизий с помощью метода открытой адресации имеет ряд
недостатков. Основным недостатком метода является эффект скучивания,
который значительно усиливается при почти заполненном массиве.
Эффект скучивания заключается в следующем. Для рассмотренного выше
примера при пустом массиве вероятность того, что новый элемент попадет в
первую позицию, равна 1/11. Пусть теперь первая позиция занята. При втором
добавлении вероятность того, что будет занята позиция два, в два раза больше,
чем вероятность попадания в остальные позиции и т.д.
Следовательно, имеет место тенденция возникновения все более длинных
последовательностей занятых подряд позиций, что увеличивает как время
поиска, так и время добавления элементов.
66
Кроме того, так как в качестве структуры хранения используется массив, т.е.
структура данных с фиксированным количеством элементов, то всегда
существует вероятность переполнения.
Метод цепочек
В этом методе для разрешения коллизий в каждую запись хеш-таблицы
добавляется указатель для поддержания связанного списка. Сами списки могут
размещаться как в памяти, принадлежащей хеш-таблице (внутренние цепочки),
так и в отдельной памяти (внешние цепочки).
Метод внешних цепочек
Хеш-таблица представляет собой массив связанных списков размера m (элементы массива обычно имеют индексы от 0 до m - 1). После вычисления
значения хеш-функции а = h(k) задача сводится к последовательному поиску в
a-ом списке (см. рис. 7.1).
Возможно, что список размещается во внешней памяти. В этом случае для
ускорения поиска желательно, чтобы записи с ключами-синонимами при
вставке попадали в один кластер файла. Если число синонимов становится
слишком большим, можно вместо линейных списков использовать дерево
поиска.
Анализ
Метод цепочек лишен большинства недостатков, присущих методу открытой
адресации. Так использование
списков
практически не ограничивает
количества добавляемых элементов.
Удаление элемента состоит в исключении узла из связного списка, что
никак не влияет на эффективность как алгоритма поиска, так и алгоритма
включения. Основным недостатком метода цепочек является то, что для
указателей требуется дополнительная память. Кроме того, если списки станут
слишком длинными, то теряет смысл вся идея хеширования.
Пример
На
рисунке
приведен
пример
заполнения
списков
следующей
последовательностью ключей: 17, 65, 93, 77, 11, 7, 15, 33,10. В качестве хешфункции используется функция (K mod 10) + 1.
1
10
2
3
4
11
0
93
33
65
15
67
17
77
7
5
6
0
7
8
0
9
10
0
0
Внутренние цепочки
В методе внутренних цепочек (см. рис.) связанные списки для синонимов
поддерживаются внутри таблицы. Для поиска свободного места в таблице
можно использовать разные методы. Например, последовательный просмотр
позиций таблицы.
При вставке новых ключей проявляется тенденция объединения хеш-адресов в
группы, что приводит к срастанию списков. Таким образом, в один список могут попасть ключи, не являющиеся синонимами по хеш-функции, удлиняя список. Часто метод внутренних цепочек называют методом срастающихся
цепочек.
1.
2.
3.
4.
5.
6.
Контрольные вопросы:
В чем заключается метод поиска - хеширование?
Перечислите основные хеш - функции?
В чем суть каждой хеш - функции?
Что такое коллизия?
Какие методы для разрешения коллизий вы знаете?
В чем заключается суть каждого метода для разрешения коллизии?
68
Пример оформления:
Рис.1 Окно задания на лабораторную работу.
Рис. 2 Окно поиска в хеш – таблице.
69
Рис.3 Окно параметров распределения записей в хеш – таблице.
Задания на лабораторную работу:
Необходимо разработать программу с использованием принципов
хеширования. Структура записей по вариантам берется из лабораторной работы
№ 1. Хеш – функцию и метод для разрешения коллизий можно выбрать любые
из перечисленных в теоретической части, которая будет наиболее подходить
для вашего варианта.
70
Список использованной литературы:
1. Д. Кнут. Искусство программирования, т.3:Сортировка и поиск -М.:
СПб: Киев, Вильямс, 2003.
2. Н. Вирт. Алгоритмы и структуры данных – СПб: Невский дилект, 2001.
3. Р. Седжвик. Фундаментальные алгоритмы на С. Анализ/Структуры
данных/Сортировка/Поиск/Алгоритмы на графах – СПб: ООО
«ДиаСофтЮП»,2003
4. Т. Кормен, Ч. Лейзерсон, Р. Ривест. Алгоритмы. Построение и анализ -М:
МЦНМО, 1999.
5. А. Ахо, Дж. Хопкрофт, Дж. Ульман. Структуры данных и алгоритмы -М:
СПб: Киев: Вильямс, 2001.
6. А. Ахо, Дж. Хопкрофт, Дж. Ульман. Построение и анализ
вычислительных алгоритмов -М.: Мир, 1979.
7. Э. Рейнгольд, Ю. Нивергельт, Н. Део. Комбинаторные алгоритмы. Теория
и практика -М.: Мир, 1980.
71
Download