
- •Алгоритмы и алгоритмические языки
- •Лекция 1 Представление чисел в эвм Целые
- •Вещественные
- •Ошибки вычислений
- •Лекция 2 Алгоритмы. Сведение алгоритмов. Нижние и верхние оценки.
- •Сортировки Постановка задачи
- •Сортировка пузырьком.
- •Сортировка слиянием с рекурсией.
- •Сортировка слиянием без рекурсии.
- •Лекция 3 Алгоритмы. Сведение алгоритмов. Сортировки и связанные с ними задачи.
- •Доказательство корректности работы алгоритма.
- •Оценки времени работы алгоритма.
- •Некоторые задачи, сводящиеся к сортировке.
- •Лекция 4 Алгоритмы. Сведение алгоритмов. Сортировки и связанные с ними задачи.
- •HeapSort или сортировка с помощью пирамиды.
- •Алгоритмы сортировки за время o(n)
- •Сортировка подсчетом
- •Цифровая сортировка
- •Сортировка вычерпыванием
- •Лекция 5 Алгоритмы. Сведение алгоритмов.
- •Порядковые статистики.
- •Поиск порядковой статистики за время (n) в среднем
- •Поиск порядковой статистики за время (n) в худшем случае
- •Язык программирования c.
- •Переменные
- •Структуры данных.
- •Вектор.
- •Лекция 6
- •Стек. Реализация 1 (на основе массива).
- •Стек. Реализация 2 (на основе массива с использованием общей структуры).
- •Стек. Реализация 3 (на основе указателей).
- •Стек. Реализация 4 (на основе массива из двух указателей).
- •Стек. Реализация 5 (на основе указателя на указатель).
- •Очередь.
- •Стандартная ссылочная реализация списков
- •Ссылочная реализация списков с фиктивным элементом
- •Реализация l2-списка на основе двух стеков
- •Реализация l2-списка с обеспечением выделения/освобождения памяти
- •Лекция 7 Структуры данных. Графы.
- •Поиск пути в графе с наименьшим количеством промежуточных вершин
- •Представление графа в памяти эвм
- •Массив ребер
- •Матрица смежности
- •Матрица инцидентности
- •Списки смежных вершин
- •Реберный список с двойными связями (для плоской укладки планарных графов)
- •Лекция 8 Структуры данных. Графы.
- •Поиск кратчайшего пути в графе
- •Алгоритм Дейкстры
- •Конец вечного цикла
- •Алгоритм Дейкстры модифицированный
- •Конец вечного цикла
- •Лекция 9 Бинарные деревья поиска
- •Поиск элемента в дереве
- •Добавление элемента в дерево
- •Поиск минимального и максимального элемента в дереве
- •Удаление элемента из дерева
- •Поиск следующего/предыдущего элемента в дереве
- •Слияние двух деревьев
- •Разбиение дерева по разбивающему элементу
- •Сбалансированные и идеально сбалансированные бинарные деревья поиска
- •Операции с идеально сбалансированным деревом
- •Операции со сбалансированным деревом
- •Поиск элемента в дереве
- •Добавление элемента в дерево
- •Удаление элемента из дерева
- •Поиск минимального и максимального элемента в дереве
- •Поиск следующего/предыдущего элемента в дереве
- •Слияние двух деревьев
- •Разбиение дерева по разбивающему элементу
- •Лекция 10 Красно-черные деревья
- •Отступление на тему языка с. Поля структур.
- •Отступление на тему языка с. Бинарные операции.
- •Высота красно-черного дерева
- •Добавление элемента в красно-черное дерево
- •Однопроходное добавление элемента в красно-черное дерево
- •Удаление элемента из красно-черного дерева
- •Лекция 11
- •Высота b-дерева
- •Поиск вершины в b-дереве
- •Отступление на тему языка с. Быстрый поиск и сортировка в языке с
- •Добавление вершины в b-дерево
- •Удаление вершины из b-дерева
- •Лекция 12 Хеширование
- •Метод многих списков
- •Метод линейных проб
- •Метод цепочек
- •Лекция 14 Поиск строк
- •Отступление на тему языка с. Ввод-вывод строк из файла
- •Алгоритм поиска подстроки с использованием хеш-функции (Алгоритм Рабина-Карпа)
- •Конечные автоматы
- •Отступление на тему языка с. Работа со строками
- •Алгоритм поиска подстроки, основанный на конечных автоматах
- •Лекция 15 Алгоритм поиска подстроки Кнута-Морриса-Пратта (на основе префикс-функции)
- •Алгоритм поиска подстроки Бойера-Мура (на основе стоп-символов/безопасных суффиксов)
- •Эвристика стоп-символа
- •Эвристика безопасного суффикса
- •Форматы bmp и rle
- •Bmp без сжатия.
Добавление элемента в дерево
Требуется добавить в дерево вершину v.
Для этого ищем лист, после которого следует вставить v и вставляем v после него.
Алгоритмом, аналогичным поиску элемента, найдем лист c, после которого следует вставить элемент v и вставим его. На языке С вставка вершины в дерево может быть выполнена следующим образом:
STree *Insert(STree *root, STree *v)
{
if(v->value>=root->value)
return root->right==NULL ?
(v->back=root,v->right=v->left=NULL,root->right=v) : Insert(root->right, v);
else
return root->left==NULL ?
(v->back=root,v->right=v->left=NULL,root->left=v) : Insert(root->left, v);
}
Отметим, что здесь активно используется разделитель выражений – запятая. Напомним, что, если несколько арифметических выражений в языке С разделены запятой, то значение всего выражения равно последнему из них.
Поиск минимального и максимального элемента в дереве
STree *SearchMin(STree *root)
{ return root->left==NULL?root: SearchMin(root->left);}
STree *SearchMax(STree *root)
{ return root->right==NULL?root: SearchMin(root-> right);}
Удаление элемента из дерева
Удаление вершины v из дерева поиска не представляет проблем, если данная вершина является листом или имеет всего одного потомка. Иначе, например, из правого поддерева v можно изъять минимальный элемент (самый левый) и поместить его на место удаленного. При этом, дерево останется деревом поиска.
Поиск следующего/предыдущего элемента в дереве
Если у текущего элемента v есть правый потомок, то следующим элементом будет минимальный элемент в поддереве, которое имеет корень v->right. Иначе мы должны подниматься вверх по дереву, пока не встретиться вершина v, являющаяся левым потомком своего родителя. В этом случае родитель этой вершины будет следующим элементом дерева.
STree *SearchNext(STree *cur)
{
if(cur==NULL)return NULL;
if(cur->right!=NULL)return SearchMin(cur->right);
while(cur->back && cur!=cur->back->left)cur=cur->back;
return cur->back;
}
Аналогично ищется предыдущий элемент.
Слияние двух деревьев
Для двух деревьев поиска T1 и T2 таких, что все элементы в T1 меньше или равны всех элементов в T2 : слияние деревьев в одно дерево поиска T.
Выбираем из дерева T2 наименьший элемент (самый левый), исключаем его из дерева T2 и делаем его корнем нового дерева T. Его левым потомком будет корень дерева T1, а правым – корень дерева T2 . Дерево T будет деревом поиска.
Далее нам встретится немного другая задача – пусть задан некоторый элемент v и два дерева T1 и T2 такие, что все элементы в T1 меньше или равны v, а все элементы из T2 - больше или равны. Слить все указанные данные в одно дерево поиска T. Элемент v, в этой ситуации, называется стыковочным. Задача в данной формулировке тривиальна.
Разбиение дерева по разбивающему элементу
Для данной вершины дерева v разбиение дерева поиска T на два дерева поиска T0 и T1 таких, что все элементы в T0 меньше v, и все элементы в T1 больше или равны v.
Для наглядности рассуждений расположим геометрически дерево поиска таким образом, чтобы вершины были упорядочены по оси OX. Проведем на графике из вершины v вертикальную линию. Все элементы в дереве слева от этой линии – меньше или равны v, а справа – больше или равны.
Вершина v имеет два поддерева, из нее выходящих, в одном из которых все элементы меньше v , а в другом – больше или равны. Назовем эти деревья T0 и T1 , соответственно.
Вершины ветви, от v до корня дерева r назовем V’ = {v1=v,v2,v3,…,vn=r }.
Поддерево, выходящее из вершины, являющейся потомком vi V’ , назовем Ti (см. рисунок выше).
Легко доказать, что верны следующие факты для любого i:
либо для любого j<i: Ti < vi Tj , Ti < vi vj (vj правому поддереву vi),
либо для любого j<i: Ti vi > Tj , Ti vi > vj (vj левому поддереву vi).
Легко увидеть, также, что все дерево T состоит из вершин, принадлежащих либо некоторому Ti , либо V’.
Итак, конструирование двух требуемых поддеревьев будем производить следующим способом. Рассмотрим, сначала поддеревья T0 и T1. Будем последовательно добавлять в них данные, чтобы получить искомые деревья.
Будем далее последовательно перебирать вершины vi для i от 2 до n.
На каждом шаге если vi vi-1, то Ti< vi T0 и мы сливаем деревья Ti и T0 c с помощью стыковочного элемента vi. Иначе vi > vi-1 , тогда Ti vi> T1 и мы сливаем деревья Ti и T1 c с помощью стыковочного элемента vi .
В силу вышесказанного, в конечном итоге, деревья T0 и T1 будут искомым разбиением исходного дерева поддеревья T с помощью вершины v.