
- •Министерство образования и науки Российской Федерации
- •Цель лекции
- •План лекции
- •1 Происхождение вычислительных машин
- •2 Изучение алгоритмов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Биты и их хранение
- •2 Оперативная память
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Устройства внешней памяти
- •3 Хранение и поиск файлов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление числовых значений
- •2 Хранение целых чисел
- •3 Хранение дробей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление текста
- •2 Представление изображений
- •Достоинства пиксельной графики
- •Недостатки пиксельной графики
- •Достоинства векторной графики
- •Недостатки векторной графики
- •3 Представление звука
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Сжатие изображений
- •2 Ошибки передачи данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Архитектура эвм
- •2 Связь процессора с другими устройствами
- •3 Другие архитектуры
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Машинный язык
- •2 Пример машинного языка
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Выполнение программы
- •2 Пример выполнения программы
- •3 Программы и данные
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Логические операции
- •2 Операции сдвига
- •3 Арифметические операции
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция операционных систем
- •2 Архитектура операционных систем
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие процесса
- •2 Управление процессами
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Классификация сетей
- •2 Сетевые протоколы*
- •3 Безопасность сетей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие алгоритма
- •2 Представление алгоритма
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Теория решения задач
- •2 Общие методы решения задач
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритм последовательного поиска
- •2 Управление циклами
- •3 Алгоритм сортировки методом вставки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритмы поиска и сортировки
- •2 Управление рекурсией
- •3 Разработка рекурсивных процедур
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эффективность алгоритмов
- •2 Верификация программ
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция и классификация языков программирования
- •2 Концепции традиционного программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Процедурные единицы
- •2 Реализация языка программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Объектно-ориентированное программирование
- •2 Декларативное программирование
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структуры данных
- •Integer Scores (2.9).
- •2 Статические и динамические структуры
- •3 Указатели
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Массивы
- •2 Списки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структура и функции стека
- •2 Реализация стека
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Очереди
- •2 Деревья
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Пользовательские типы данных
- •Int Age;
- •2 Классы
- •Int *StackEntries;
- •3 Стандартная библиотека шаблонов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Роль операционной системы
- •2 Последовательные файлы
- •3 Вопросы программирования
- •0000000010000110
- •001100010011001100110100
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения индексации
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения хеширования
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Общие вопросы
- •2 Система управления базой данных
- •3 Поддержка целостности баз данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Модели баз данных
- •2 Реляционная модель баз данных
- •3 Объектно-ориентированные базы данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Интеллект и машины
- •2 Распознавание образов
- •3 Мышление
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Искусственные нейронные сети
- •2 Генетические алгоритмы
- •Контрольные вопросы
- •Невычислимые функции Цель лекции
- •План лекции
- •1 Основы машины Тьюринга
- •2 Невычислимая функция
- •3 Сложность задач
- •Листинг 1. Процедура MergeLists для объединения двух упорядоченных списков
- •Листинг 2. Алгоритм сортировки слиянием, реализованный в процедуре MergeSort
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Шифрование с открытым ключом
- •2 Модульная арифметика
- •Контрольные вопросы
- •Литература
- •Internet-ресурсы
Контрольные вопросы
1. Что общего и в чем различие между циклом и рекурсией?
2. Поясните на примере утверждение, что язык Си++ поддерживает рекурсивные функции.
3. Как работает рекурсивная функция? Поясните на примере.
4. Какие недостатки присущи рекурсивным алгоритмам?
5. Как завершить выполнение рекурсивных алгоритмов?
Лекция № 18 Эффективность и правильность алгоритмов
Цель лекции
Изучить показатели и методы оценки эффективности алгоритмов.
План лекции
1. Эффективность алгоритмов.
2. Верификация программ.
В этой лекции мы обсудим понятия, которые являются частью данного формального введения в теорию алгоритмов. О них всегда нужно помнить при самостоятельной разработке алгоритмов. Первое из них — эффективность, а второе — правильность.
1 Эффективность алгоритмов
Хотя современные машины способны выполнять миллионы операций в секунду, эффективность по-прежнему остается важнейшим аспектом разработки алгоритмов. Зачастую выбор между эффективным и неэффективным решением задачи может на самом деле означать выбор между реализуемым и нереализуемым способом ее решения.
Рассмотрим задачу, с которой сталкивается секретарь университета при поиске личных дел студентов и их заполнении. Хотя в университете на протяжении любого семестра фактически числится около 10 000 студентов, секретарю в действительности приходится иметь дело с более чем 30 000 личных дел, поскольку за несколько предыдущих лет многие из студентов зарегистрировались для изучения хотя бы одной из преподаваемых в университете дисциплин, но не смогли закончить цикл обучения. Теперь предположим, что все личные дела хранятся в компьютере секретаря в виде списка, упорядоченного по идентификационным номерам каждого из студентов. Чтобы найти личное дело некоторого студента, секретарь должен выполнить поиск по его идентификационному номеру в общем списке.
Мы уже познакомились с двумя алгоритмами поиска в подобных списках последовательным и двоичным поиском. Сейчас нам нужно дать ответ на вопрос, почувствует ли секретарь разницу между этими двумя алгоритмами? Начнем с рассмотрения последовательного поиска.
При заданном идентификационном номере студента алгоритм последовательного поиска начинает работу с начала списка и последовательно сравнивает каждый выбираемый элемент с искомым числом. Не зная, что представляет собой искомое число, мы не можем определить, насколько далеко потребуется просматривать список. Все же можно утверждать, что для множества выполненных операций поиска их средняя глубина будет равна приблизительно половине длины списка, хотя в отдельных случаях поиск потребует меньшего числа операций, а в других — большего Можно сделать вывод, что при многократном выполнении последовательного поиска на каждый случай в среднем приходится приблизительно 15 000 просмотренных личных дел. Если выборка каждого личного дела из памяти и сравнение его номера с искомым выполняется за десять миллисекунд (десять тысячных долей секунды), то среднее время поиска будет составлять 150 секунд или две с половиной минуты. Если секретарю придется так долго ожидать появления на экране монитора личного дела интересующего его студента, несомненно, что этот вариант совершенно неприемлем. Даже если время выборки и проверки каждой записи сократить до одной миллисекунды, на поиск личного дела студента все равно потребуется в среднем около 15 секунд — все еще слишком много для среднего времени ожидания ответа, которое можно считать приемлемым.
В противоположность этому, алгоритм двоичного поиска начинает работу со сравнения искомого значения со средним элементом списка. Если это не искомый элемент, то область поиска сразу же сужается до половины исходного списка, т.е. после проверки среднего элемента списка из 30000 личных дел алгоритм двоичного поиска в большинстве случаев выберет для дальнейшего рассмотрения только 15000 Дел. После второго этапа область поиска в большинстве случаев сократится до 7500 Дел, после третьего — до 3750 и т.д. В результате искомое значение будет найдено при выборе, самое большее, 15 элементов списка, состоящего из 30000 дел. Таким образом, если каждое выбранное значение обрабатывается за 10 миллисекунд, процесс поиска нужного личного дела потребует не более 0,15 секунды, а это означает, что с точки зрения секретаря личное дело любого студента будет появляться на экране практически мгновенно. Можно сделать обоснованное заключение, что выбор между алгоритмом последовательного поиска и алгоритмом двоичного поиска в данном случае имеет большое значение1.
Этот пример иллюстрирует важность той области компьютерных наук, которую называют анализом алгоритмов. Эта область связана с изучением необходимых алгоритмам ресурсов, таких как время или используемый объем памяти. Основным практическим применением результатов подобных исследований является оценка относительных достоинств альтернативных алгоритмов. В нашем случае мы проанализировали время, требующееся алгоритмам последовательного и двоичного поиска, что позволило нам определить, какой из них больше подходит в данном конкретном случае. В общем случае такой анализ осуществляется в более широком контексте. Это означает, что при рассмотрении алгоритмов, выполняющих поиск в списке, мы не ограничимся списком фиксированной длины, но пытаемся вывести формулу эффективности алгоритма для списков произвольной длины. Такой анализ включает изучение ситуаций, в которых алгоритм демонстрирует свои наилучшие свойства, ситуаций, когда его эффективность минимальна, а также оценку его средней производительности.
В
предыдущем случае выполненный нами
анализ заключался в оценке средней
производительности алгоритма
последовательного поиска, а также
определении той производительности,
которую алгоритм двоичного поиска
продемонстрирует в наихудшем случае.
Хотя мы рассматривали список определенной
длины, несложно обобщить наши рассуждения
на случай списка произвольной длины. В
частности, при применении к списку из
п
элементов
алгоритму последовательного поиска в
среднем потребуется проверить
элементов,
тогда как алгоритму двоичного поиска
в самом худшем случае потребуется
проверить только
элементов.
(В данном случае выражение
представляет
логарифм числа п
по
основанию 2, который показывает, сколько
раз число и можно разделить на два.)
Чтобы воспользоваться преимуществами алгоритма двоичного поиска, личные дела студентов должны располагаться в памяти машины таким образом, чтобы можно было извлекать средние записи последовательно уменьшающихся подсписков без чрезмерных усилий. Это можно осуществить, запоминая личные дела в индексированных файлах-структурах, которые будут обсуждаться далее. Кроме того, тех же результатов можно достичь и с использованием хешированных файловых структур, которые также описываются далее.
Давайте попробуем проанализировать аналогичным образом алгоритм сортировки методом вставки (см. рис. 1). Поскольку основным действием в реализации данного алгоритма является сравнение двух имен, наш подход будет состоять в подсчете количества таких сравнений, которые потребуется выполнить при сортировке списка длиной п элементов.
Рисунок 1 - Работа алгоритма сортировки методом вставки в наихудшем случае
Вспомним,
что при сортировке методом вставки
осуществляется выбор некоторого
элемента, называемого опорным; после
этого он сравнивается с предшествующими
ему элементами, пока для него не будет
найдено надлежащее место, после чего
опорный элемент вставляется в
соответствующую позицию. Алгоритм
начинается с выбора второго элемента
списка в качестве опорного. По мере его
выполнения в качестве опорных выбираются
следующие элементы — пока не будет
достигнут конец списка. В самом лучшем
случае каждый опорный элемент уже
находится на положенном ему месте.
Следовательно, чтобы это было обнаружено,
его потребуется сравнять только с одним
именем. Поэтому в наилучшем случае
применение алгоритма сортировки методом
вставки к списку из п
элементов
потребует выполнения
сравнений. (Второй элемент сравнивается
с одним элементом (первым), третий элемент
— с одним элементом (вторым) и т.д.)
И
наоборот, наихудший сценарий имеет
место в том случае, когда каждый опорный
элемент потребуется сравнивать со всеми
впереди
стоящими элементами, прежде чем удастся
найти правильное место его расположения.
Очевидно, что в этом случае исходный
список упорядочен в обратном порядке.
Первый опорный элемент (второй элемент
списка) сравнивается с одним элементом,
второй опорный элемент (третий элемент
списка) — с двумя элементами и т.д. (рис.
1). Следовательно, общее количество
сравнений при сортировке списка из n
элементов составит
,
что эквивалентно
или
.
В частности, для списка из 10 элементов
алгоритму сортировки методом вставки
в наихудшем случае потребуется выполнить
45 сравнений.
В среднем при сортировке методом вставки можно ожидать, что каждый опорный элемент потребуется сравнить с половиной предшествующих ему элементов. В этом случае общее количество выполненных сравнений будет вдвое меньше, чем в наихудшем случае, т.е. (1/4)(п2 - п) сравнений для списка длины п. Например, если использовать сортировку методом вставки для упорядочения множества списков из 10 элементов, то среднее число производимых в каждом случае сравнений будет равно 22,5.
Важность
полученного выше результата состоит в
том, что количество сравнений, выполненных
алгоритмом сортировки методом вставки,
позволяет оценить время, которое
потребуется для выполнения сортировки.
Эта оценка была использована для
построения графика, представленного
на рис. 2. Он показывает, как будет
возрастать время, необходимое для
выполнения сортировки методом вставки,
при увеличении длины сортируемого
списка. Данный график построен по оценкам
работы алгоритма в наихудшем случае,
когда, исходя из результатов наших
исследований, для списка длиной п
требуется
выполнить не менее
сравнений элементов. На графике отмечено
несколько конкретных значений длины
списка и указано время, необходимое в
каждом случае. Обратите внимание, при
увеличении длины списка на одно и то же
количество элементов время, необходимое
для сортировки списка, все больше и
больше возрастает. Таким образом, с
увеличением длины списка эффективность
данного алгоритма уменьшается.
Рисунок 2 - График зависимости времени сортировки от длины списка при сортировке методом вставки
Выполним аналогичный анализ работы алгоритма двоичного поиска в наихудшем случае. Как было установлено выше, при использовании этого алгоритма для поиска в списке из п элементов потребуется проанализировать не более log2 и элементов. Это позволяет оценить время, необходимое для выполнения алгоритма при различной длине сортируемого списка. На рис. 3 представлен график, построенный по результатам данного анализа. На этом графике также отмечены конкретные значения длины списка, возрастающие на одну и ту же величину, и указано соответствующее время выполнения алгоритма. Обратите внимание, что темпы роста времени выполнения алгоритма снижаются по мере увеличения длины списка, т.е. эффективность алгоритма двоичного поиска возрастает с увеличением длины списка.
Рисунок 3 - График зависимости времени поиска от длины списка для алгоритма двоичного поиска
Основным
отличием между графиками, представленными
на рис. 2 и 3, безусловно, является их
общая форма. Именно форма графика, а не
его индивидуальные особенности,
демонстрирует, насколько хорошо данный
алгоритм будет справляться с все
возрастающими объемами данных. Заметим,
что общая форма графика определяется
типом отображаемого выражения, а не его
конкретными особенностями: все линейные
выражения изображаются прямой линией,
все квадратичные выражения — параболической
кривой, а все логарифмические выражения
порождают логарифмическую кривую,
подобную представленной на рис.3. Общую
форму кривой принято определять
простейшим выражением, порождающим
кривую данной формы. В частности,
параболическая форма обычно определяется
выражением
,
а логарифмическая — выражением
.
Выше
было показано, что форма графика,
представляющего зависимость времени
выполнения алгоритма от объема входных
данных, отражает общие характеристики
эффективности алгоритма. Поэтому принято
классифицировать алгоритмы согласно
форме их графиков, построенных для
самого неблагоприятного случая. Способ
обозначения, используемый для определения
этих классов, иногда называют тэта-классами.
Алгоритмы, графики которых имеют
параболическую форму (например, сортировка
методом вставки), относятся к классу,
алгоритмы, графики которых имеют
логарифмическую форму (например, двоичный
поиск), - к классу
.
Любой алгоритм из тэта-класса
по самой свой сути всегда более эффективен,
чем алгоритм из тэта-класса
.