Upload
mikhail-kurnosov
View
686
Download
1
Embed Size (px)
DESCRIPTION
Citation preview
Лекция 1Введение в алгоритмы
Курносов Михаил Георгиевич
к.т.н. доцент Кафедры вычислительных систем Сибирский государственный университет
телекоммуникаций и информатики
http://mkurnosov.net/teaching
Литература
2
Кормен Т.Х., Лейзерсон Ч.И., Ривест Р.Л., Штайн К. Алгоритмы: построение и анализ. – 3-е изд. – М.: Вильямс, 2013 [CLRS].
Левитин А.В. Алгоритмы: введение в разработку и анализ. – М.: Вильямс, 2006. – 576 с. [Levitin]
Ахо А.В., Хопкрофт Д., Ульман Д.Д. Структуры данных и алгоритмы. – М.: Вильямс, 2001. – 384 с. [AHU]
Седжвик Р. Фундаментальные алгоритмы на С++. Анализ/Структуры данных/Сортировка/Поиск. – К.: ДиаСофт, 2001. – 688 с.
Макконнелл Дж. Основы современных алгоритмов. – 2е изд. – М.: Техносфера, 2004. – 368 с.
Скиена С.С. Алгоритмы. Руководство по разработке. – 2-е изд. – СПб: БХВ, 2011 – 720 с.
Керниган Б.В., Пайк Р. Практика программирования. – СПб.: Невский Диалект, 2001. – 381 с.
Кнут Д. Искусство программирования. Том {1, 3}, 3-е изд. - М.: Вильямс, 2010.
Понятие алгоритма
3
Алгоритм (algorithm) – это конечная последовательность инструкций (предписаний) исполнителю, в результате выполнения которой обеспечивается получение требуемого результата из исходных данных (неформально определение)
Уточнения
Алгоритм должен описываться на формальном языкеисполнителя, исключающем неоднозначность толкования
Множество инструкций конечно
Запись алгоритма на формальном языке называется программой (program)
Свойства алгоритмов
4
Дискретность – алгоритм представляется как последовательность инструкций исполнителя. Каждая инструкций выполняется только после того, как закончилось выполнение предыдущего шага
Конечность (результативность, финитность) – алгоритм должен заканчиваться после выполнения конечного числа инструкций
Массовость – алгоритм решения задачи должен быть применим для некоторого класса задач, различающихся лишь значениями входных данных
Детерминированность (определенность) – каждый шаг алгоритма должен быть точно определен – записан на формальном языке исполнителя. Детерминированность обеспечивает одинаковость результата, получаемого при многократном выполнении алгоритма, на одном и том же наборе входных данных.
Пример
5
Задан массив h[n], содержащий рост каждого студента 1-го курса. Требуетсяразработать алгоритм поиска студента k с максимальным ростом
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
180 155 193 176 159 169 172 195 201 160 167 180 177 174 179 187 166 193 183 175 169 170 157 199 187
h[25]:
k = 8
algorithm MaxHeight(h, n)
hmax = 0
for i = 0 to n – 1 do
if h[i] > hmax then
hmax = h[i]
k = i
end if
end for
return k
end algorithm
Свойства алгоритма
Дискретность?
Конечность?
Массовость?
Детерминированность?
Показатели эффективности алгоритмов
6
1. Время выполнения (execution time) – временная эффективность
2. Объем потребляемой памяти (memory consumption) –пространственная эффективность
3. Объем потребляемой электроэнергии(energy consumption)
Анализ времени выполнения алгоритмов
7
Что влияет на время выполнения алгоритма (программы)?
1. Размер входных данных
2. Качество реализации алгоритма на языке программирования
3. Качество скомпилированного кода
4. Производительность вычислительной машины
Для многих алгоритмов время их выполнения зависит не от значений входных данных, а от их размера/количества
Например, в алгоритме поиска самого высокого студента время выполнения определяется не значениями в массиве, а его длиной
Входные данные
Алгоритм (программа)
Вычислительная машина
Компилятор,интерпретатор
Анализ времени выполнения алгоритмов
8
У каждого алгоритма есть параметры, определяющие размеры его входных данных
Поиск минимума в массиве: n – количество элементов в массиве
Умножения матриц: n, m – количество строки и столбцов в матрице
Сравнения двух строк: s1, s2 – длина первой и второй строк
Поиск кратчайшего пути в графе между двумя вершинами: n, m – количество вершин и ребер в графе
Анализ времени выполнения алгоритмов
9
Время выполнения алгоритма можно оценить путем подсчета количества “базовых операций” выполняемых им
Количество операций алгоритма можно выразить как функциюот размера входных данных: T(n), T(s1, s2), T(n, m)
При подсчете количества операций в алгоритме принимаются следующие допущения о гипотетической вычислительной машине (исполнителе):
для выполнения “простой” операции (+, - , *, /, =, if, call) требуется один временной шаг (такт вычислительной машины)
обращение к памяти (чтение, записи) выполняется за один временной шаг
циклы и подпрограммы состоят из последовательности простых операций
Поиск минимального элемента в массиве
10
1 algorithm MaxHeight(h, n)
2 hmax = 0
3 for i = 0 to n – 1 do
4 if h[i] > hmax then
5 hmax = h[i]
6 k = i
7 end if
8 end for
9 return k
Вычислим количество T(n) операций, выполняемых алгоритмом поиска
максимального элемента в массиве из n элементов
Результат условного ветвления заранее неизвестен
Рассматриваем худшей случай (worst case) – условие выполняется всегда
Ветвление if – 1 операция
Сравнение h[i] > hmax – 1 операция
T(n) = 1 + (2 + 2)n + 1 = 2 + 4n
Количество T(n) операций, выполняемых алгоритмом в худшем случае:
Можно было также учесть 2 операции для цикла for (сравнение и переход)
Сортировка массива методом “пузырька”
11
Algorithm BubbleSort(v[1:n], n)
for i = 1 to n – 1 do
for j = n to i + 1 do
if v[j - 1] > v[j] then
temp = v[j - 1]
v[j - 1] = v[j]
v[j] = temp
end if
end for
end for
Оценим количество T(n) операций, выполняемых алгоритмом в худшем случае
2 + 2 + 2 + 1 = 7 операций
Сколько раз выполняется цикл?
Цикл 2 выполняется n – 1 раз:
n to 2, n to 3, …, n to n – 1
Суммарное количество итераций цикла 2:
(n – 2 + 1) + (n – 3 + 1) + …+ (n – n + 1) =
(n – 1) + (n – 2) + … + 1 = ?𝑺𝒏 =
𝒂𝟏 + 𝒂𝒏𝟐
𝒏
𝑻 𝒏 = 𝟕𝟏 + 𝒏 − 𝟏
𝟐𝒏 − 𝟏 = 𝟕
𝒏 𝒏 − 𝟏
𝟐=𝟕𝒏𝟐
𝟐−𝟕𝒏
𝟐
Асимптотический анализ сложности алгоритмов
12
Вычислительная сложность алгоритма (computational complexity) – это оценка количества операций выполняемых алгоритмом в зависимости от размера его входных данных
При асимптотическом анализе вычислительной сложности алгоритма (asymptotic computational complexity)рассматривается поведение алгоритма при n∞
Причины
1. Точное значение временной сложности зависит от определения элементарных операций исполнителя (например, сложность можно измерять в количестве арифметических операций, битовых операций или операций на машине Тьюринга)
2. При увеличении размера входных данных (n∞) вклад постоянных множителей и слагаемых низших порядков становится незначительным
Асимптотический анализ сложности алгоритмов
13
Известно количество операций T(n), выполняемых двумя разными алгоритмами:
T1(n) = 95n2 + 405n + 1997
T2(n) = 2n3 + 12
Какой алгоритм эффективнее с точки зрения времени выполнения?
Какой алгоритм выбрать для практического использования?
Асимптотический анализ сложности алгоритмов
14
T1(n) = 95n2 + 405n + 1997
T2(n) = 2n3 + 12
T(n)
n
Асимптотический анализ сложности алгоритмов
15
T1(n) = 95n2 + 405n + 1997
T2(n) = 2n3 + 12
T(n)
n
Начиная с определенного n быстрее работает
алгоритм 1
Асимптотический анализ сложности алгоритмов
16
При асимптотическом анализе вычислительной сложности алгоритма оценивают количество операций для следующих случаев:
худший случай (worst case) – максимальное количество операций, требуемых для обработки набора входных данных
средний случай (average case) – среднее количество операций, требуемых для обработки набора входных данных
наилучший случай (best case) – минимальное количество операций требуемых для обработки набора входных данных
Для записи асимптотической оценки вычислительной сложности алгоритмов используются асимптотические обозначения –О-нотацию (Big O)
O-обозначения
17
Пусть f(n) – это количество операций выполняемых алгоритмом
О-обозначение f(n) = O(g(n))
𝒇 𝒏 ∈ 𝑶 𝒈(𝒏) =∃𝒄 > 𝟎, 𝒏𝟎 > 𝟎:
𝟎 ≤ 𝒇 𝒏 ≤ 𝒄𝒈 𝒏 , ∀𝒏 ≥ 𝒏𝟎
Существуют положительные константы c и n0 такие, что f(n) ≤ c∙g(n) для всех n ≥ n0 (c > 0, n0 > 0)
Функция f(n) ограничена сверху функцией g(n) с точность до постоянного множителя
Используется чтобы показать, что функция (время работы алгоритма) растет не быстрее чем функция g(n) n0
cg(n)
f(n)
n
Ω-обозначения
18
Пусть f(n) – это количество операций выполняемых алгоритмом
Ω-обозначение f(n) = Ω(g(n))
𝒇 𝒏 ∈ Ω 𝒈(𝒏) =∃𝒄 > 𝟎, 𝒏𝟎 > 𝟎:
𝟎 ≤ 𝒄𝒈 𝒏 ≤ 𝒇 𝒏 , ∀𝒏 ≥ 𝒏𝟎
Функция f(n) ограничена снизу функцией g(n) с точность до постоянного множителя
Используется чтобы показать, что функция (время работы алгоритма) растет не медленнее чем функция g(n)
nn0
cg(n)
f(n)
Θ-обозначения
19
Пусть f(n) – это количество операций выполняемых алгоритмом
Θ-обозначение f(n) = Θ(g(n))
𝒇 𝒏 ∈ Θ 𝒈(𝒏) =
∃𝒄𝟏 > 𝟎, 𝒄𝟐 > 𝟎, 𝒏𝟎 > 𝟎:
𝟎 ≤ 𝒄𝟏𝒈 𝒏 ≤ 𝒇 𝒏 ≤ 𝒄𝟐𝒈 𝒏 ,∀𝒏 ≥ 𝒏𝟎
Функция f(n) ограничена снизу и сверху функцией g(n) с точность до постоянного множителя
nn0
c2g(n)
f(n)
c1g(n)
Пример
20
Пусть 𝑓 𝑛 =1
2𝑛2 − 3𝑛 (количество операций в алгоритме)
Докажем, что 𝑓 𝑛 = Θ 𝑛2
Доказательство следует из определения Θ-обозначения:
∃𝑐1 > 0, 𝑐2 > 0, 𝑛0 > 0:
0 ≤ 𝑐1𝑛2 ≤
1
2𝑛2 − 3𝑛 ≤ 𝑐2𝑛
2, ∀𝑛 ≥ 𝑛0
Необходимо найти 𝒄𝟏, 𝒄𝟐, 𝒏𝟎
Пример
21
Необходимо найти 𝒄𝟏 > 𝟎, 𝒄𝟐 > 𝟎,𝒏𝟎 > 𝟎:
0 ≤ 𝑐1 ≤1
2−3
𝑛≤ 𝑐2, ∀𝑛 ≥ 𝑛0
-3,0000
-2,5000
-2,0000
-1,5000
-1,0000
-0,5000
0,0000
0,5000
1,0000
1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46
n
1
2−3
𝑛
𝑐1 =1
14, 𝑛 ≥ 7
𝑐2 =1
2, 𝑛 ≥ 1
𝑛0 = 7
Асимптотические обозначения
22
nn0
cg(n)
f(n)
O-большое
nn0
cg(n)
f(n)
Θ-большое
nn0
c1g(n)
f(n)
Ω-большое
c2g(n)
3n2 – 100n + 6 = O(n2)
Вычислительная сложность алгоритма поиска минимального элемента в массиве: T(n) = 1 + (2 + 2)n + 1 = 2 + 4n, T(n) = O(n) – линейная относительно n
Вычислительная сложность алгоритма сортировки методом “пузырька”:
𝑇 𝑛 =7𝑛2
2−7𝑛
2T(n) = O(n2)
Свойства O, Θ, Ω
23
1. O(f(n)) + O(g(n)) = O(max(f(n), g(n)))
Пример: n3 + n2 + n + 1 = O(n3)
2. O(c∙f(n)) = O(f(n))
Пример: O(4n3) = O(n3)
3. O(f(n)) * O(g(n)) = O(f(n) * g(n))
Пример: O(n3) * O(n) = O(n4)
Основные классы сложности
24
Класс сложности Название
O(1) Константная сложность
O(log(n)) Логарифмическая сложность
O(n) Линейная сложность
O(nlogn) n-log-n сложность
O(n2) Квадратичная сложность
O(n3) Кубическая сложность
O(2n) Экспоненциальная сложность
O(n!) Факториальная сложность
Пространственная эффективность
25
Algorithm BubbleSort(v[1:n], n)
for i = 1 to n – 1 do
for j = n to i + 1 do
if v[j - 1] > v[j] then
temp = v[j - 1]
v[j - 1] = v[j]
v[j] = temp
end if
end for
end for
Какова “сложность по памяти” алгоритма сортировки методом “пузырька”?
Сколько ячеек памяти требуется алгоритму (не учитывая входной массив)?
Пространственная эффективность
26
Algorithm BubbleSort(v[1:n], n)
for i = 1 to n – 1 do
for j = n to i + 1 do
if v[j - 1] > v[j] then
temp = v[j - 1]
v[j - 1] = v[j]
v[j] = temp
end if
end for
end for
Какова “сложность по памяти” алгоритма сортировки методом “пузырька”?
Сколько ячеек памяти требуется алгоритму (не учитывая входной массив)?
Переменные i, j, temp
занимаю 3 ячейки
памяти
T(n) = 3 = O(1)
Константная сложность
по памяти
Домашнее чтение
27
Обязательное чтение
[CLRS, С. 87-97] “Глава 3. Рост функций”
[AHU, С. 28-37] “1.4 Время выполнения программ”
Дополнительное чтение
[Levitin, С. 72] “Основы анализа эффективности алгоритмов”