- •1. Вычислительные модели. Показатели эффективности алгоритмов, задача анализа алгоритмов. Время выполнения алгоритма для худшего и среднего случая. Вычислительные модели
- •Задача анализа алгоритмов
- •Время работы алгоритма
- •Время выполнения в худшем и среднем случае
- •5. Анализ рекурсивных алгоритмов. Анализ вставки элемента в бинарное дерево поиска.
- •5.Анализ сложности рекурсивных алгоритмов
- •6. Связные списки: однонаправленные, двунаправленные, кольцевые. Примеры реализации.
- •Однонаправленные (односвязные) списки
- •Двунаправленные (двусвязные) списки
- •7. Структура данных "стек". Реализация с помощью массива и связного списка, смешанная реализация. Пример использования (кроме задачи о скобках)
- •8.Структура данных "очередь". Реализация с помощью массива, циклического массива, односвязного списка.
- •Очереди
- •Бинарные деревья
- •11. Обходы бинарных деревьев (клп - "Корень-Левое-Правое" ,лкп,лпк) с примерами программной реализации.
- •12. Удаление элемента из бинарного дерева поиска.
- •13.Рандомизированные деревья. Вставка элемента в рандомизированное бинарное дерево поиска.
- •Включение элемента в рандомизированное дерево
- •Рекурсивный алгоритм вставки в рандомизированное дерево:
- •14.Быстрая сортировка Хоара (QuickSort)
- •Краткое описание алгоритма
- •Алгоритм
- •Оценка эффективности
- •15. Сортировка слиянием (MergeSort)
- •16.Полный перебор подмножеств
- •17. Полный перебор перестановок
- •18. Перебор с возвратом и отсечением вариантов
- •3.1 Использование рекурсии для записи алгоритма
- •3.2 Примеры решения задач при помощи перебора с возвратом
- •.1 Отсечение лишних вариантов
- •19. Динамическое программирование. Разбиение задачи на подзадачи, принцип оптимальности. Задача о маршруте из верхнего угла таблицы в нижний
- •20. Пример использования динамического программирования для подсчета количеств комбинаторных объектов - найти количество разбиений числа на слагаемые
- •21. Жадные алгоритмы. Принцип жадного выбора, свойство оптимальности для подзадач, схема доказательства корректности жадного алгоритма. Задача о заявках.
- •Принцип жадного выбора
- •Оптимальность для подзадач
- •Примеры Размен монет
- •Выбор заявок
- •22. Хеширование с цепочками. Эффективность хеширования с цепочками. Хеш-функции, качество хеш-функций, подходы к построению хеш-функций.
- •23. Хеширование с открытой адресацией. Способы разрешения коллизий. Анализ эффективности.
11. Обходы бинарных деревьев (клп - "Корень-Левое-Правое" ,лкп,лпк) с примерами программной реализации.
1. Обход бинарного дерева в прямом порядке:
а) Обработать корень (например, вывести в выходную последовательность его имя);
b) Обойти левое поддерево корня в прямом порядке;
c) Обойти правое поддерево корня в прямом порядке.
Обход приведённого бинарного дерева в прямом порядке даст: ABCDEFGH.
2. Обход бинарного дерева в обратном порядке:
a) Обойти левое поддерево корня в обратном порядке;
b) Обработать корень;
c) Обойти правое поддерево корня в обратном порядке.
Обход приведённого бинарного дерева в обратном порядке даст: CBEDAGFH.
3. Обход в бинарного дерева в концевом порядке:
а) Обойти левое поддерево корня в концевом порядке;
b) Обойти правое поддерево корня в концевом порядке.
c) Обработать корень;
Обход приведённого бинарного дерева в концевом порядке даст: CEDBGHFA.
Следует обратить внимание на то, что при обходе бинарного дерева в прямом порядке, любая его вершина , рассматриваемая как корень, посещается перед обходом поддеревьев этого корня, а при концевом порядке – после.
В случае же обратного обхода бинарного дерева, корень любого его поддерева (и самого этого дерева в целом) посещается непосредственно после обхода левого поддерева и перед обходом правого поддерева этого корня.
Помимо указанных трёх основных порядков обхода, на практике иногда применяется ещё один – поуровневый обход (обход вширину) бинарного дерева, при котором вершины бинарного дерева начиная с корня перечисляются последовательно слева направо, уровень за уровнем.
Для нашего примера указанный порядок обхода даст последовательность: ABFCDGHE.
Необходимые для программной обработки бинарных деревьев операции их ввода-вывода, требуют возможности строчного представления бинарных деревьев в форме последовательности знаков.
Одним из простых способов такого представления является скобочная запись бинарных деревьев, суть которой ясна из следующей кодировки бинарного дерева рис.1:
( ( (*С*) B ( (*E*)D* ) ) A ( (*G*)F(*H*) ) )
В приведённой выше записи, знаком '*’ обозначены пустые поддеревья, и для лучшей читабельности, добавлены лишние пробелы.
12. Удаление элемента из бинарного дерева поиска.
Удаление элемента из множества.
Удаление – несколько более сложная процедура, чем вставка. Пусть нам надо удалить элемент x. Найдём узел r, который его содержит. Если такого узла найти не удалось, то и делать ничего не надо.
Если у узла r нет сыновей, то всё хорошо: уничтожаем узел и пишем NIL в указатель, который на него ссылался.
Если у узла только один сын, то тоже всё понятно: уничтожаем узел, а в указатель, который на него ссылался, заносим адрес сына.
Наконец, что делать, если у удаляемого узла r два сына? В этом случае нам надо найти в его правом поддереве узел с самым маленьким элементом. Это несложно: берём правого сына и идём от него влево, пока не найдём узел q, у которого левого сына нет. Он и будет искомым. Теперь значение из q запишем в узел r, а удалять будем уже не r, а q. Как это делается, см. выше.
Приведём пример реализации (для удобства он сделан в виде рекурсивной процедуры. Для экономии места в стеке внутренняя рекурсивная процедура вложена во внешнюю и пользуется её параметром x и локальными переменными):
procedure del(var root: PNode; x: Integer);
var
p,q: PNode;
procedure del_rec(var r: PNode);
begin
if r=NIL then exit;
if x<r^.v then begin del_rec(r^.left); exit; end;
if x>r^.v then begin del_rec(r^.right); exit; end;
if (r^.left=NIL) or (r^.right=NIL) then
begin
p:=r;
if r^.left=NIL then r:=r^.right else r:=r^.left;
dispose(p);
exit;
end;
p:=r^.right;
if p^.left=nil then
begin
r^.v:=p^.v;
r^.right:=p^.right;
dispose(p);
exit;
end;
//идём влево, пока есть куда
q:=p^.left;
while q^.left<>NIL do begin
p:=q; q:=q^.left;
end;
//значение из q^ кинем в r^, и удалять будем уже не r^, а q^
r^.v:=q^.v;
p^.left:=q^.right;
dispose(q);
end;
begin
del_rec(root);
end;