- •Рекурсивные определения и вычисления. Рекурсивные функции и процедуры. Модель исполнения рекурсивных подпрограмм компьютером. (Лек 1.1)
- •. Рекурсивные определения и вычисления
- •If b then e1 else e2 (где e1, e2 - выражения)
- •Накапливающие параметры. (Лек 1.2)
- •Абстрактная модель последовательности и линейные сд (стек, очередь, дек). (Лек 4)
- •Аксиомы
- •Реализация с массивом
- •Алгоритм перестроения дерева Хаффмана
- •Идеально сбалансированные бинарные деревья. (Лек 8).
Аксиомы
(для p: α; s: Stack (α); t: Non_null_stack (α)):
A1) Null (Create) = true;
A2) Null (Push (p, s)) = false;
A3) Top (Push (p, s)) = p;
A4) Pop (Push (p, s)) = s;
A5) Push (Top (s), Pop (s)) = s.
Абстрактный тип Stack (α)
фактически (с точностью до обозначений и несущественных деталей)
совпадает с типом L_list (α).
Пример
s := Push (a, s);
s := Push (b, s);
s := Pop (s);
s := Push (d, s);
s := Pop (s);
e := Top (s);
Top (Pop (Push (d, Pop (Push (b, Push (a, s)))))) =
=Top (Pop (Push (d, Push (a, s)))) =
=Top (Pop (Push (d, Push (a, s)))) =
=Top (Push (a, s)) = a
Можно определить функцию (процедуру) Pop2, совмещающую результат действия
функций Top и Pop:
Pop2: Non_null_stack (α) α Stack (α).
void Push2 (El a, Stack &s );
// добавить элемент a в стек s
Void Pop2 (El &a, Stack &s);
//вытолкнуть элемент из стека s и сохранить его в a
Пусть задано состояние двух стеков s1 = [1] и s2 = [2, 3, 4]. Тогда после выполнения действий
While (!Null (s2)) {
Pop2 (a, s2);
Push2 (a, s1);
}
состояние стеков есть s1 = [???] и s2 = [???].
s1 = [4, 3, 2, 1] и s2 = [ ]
Непрерывная реализация ограниченного стека на базе вектора
Для представления стека используется:
одномерный массив (вектор) Mem: array [0..n] of α
переменная Верх: 0..n (-1..n)
Для пустого стека Верх == -1.
Для целиком заполненного стека Верх == n.
Вершина стека доступна как Mem [Верх].
Операция Pop реализуется как Верх = Верх 1.
Операция Push (p, s) как
{Верх = Верх + 1; Mem [Верх] = p }
при -1 ≤ Верх < n.
Два стека, ограниченных в совокупности, на базе одного вектора
Очередь. Формальные определения, спецификации, программные реализации. (Лек 4)
Функциональная спецификация очереди из элементов типа α (Queue of α Queue (α))
1) Create : Queue (α);
2) Null : Queue (α) Boolean;
3) First : Non_null_queue (α) α;
4) Rest : Non_null_queue (α) Queue (α);
5) Postfix : Queue (α) α Queue (α)
Аксиомы для очереди (p: α; q: Queue (α)): A1) Null (Create) = true;
A2) Null (Postfix (q, p)) = false;
A3) First (Postfix (q, p)) =
= if Null (q) then p else First (q);
A4) Rest (Postfix (q, p)) =
= if Null (q) then Create else Postfix (Rest (q), p).
Пример Функция сцепления двух очередей q1 и q2:
Concat (q1, q2) ≡
≡ if Null (q1) then q2
else if Null (q2) then q1
else {not Null (q1) & not Null (q2)}
Concat (Postfix (q1, First (q2)), Rest (q2))
Непрерывная реализация ограниченной очереди на базе вектора
Вектор Mem [0..n]
Переменные Начало, Конец: 0..n, идентифицирующие начало и конец очереди
Двух переменных Начало и Конец недостаточно, чтобы различить в данном представлении два следующих состояния очереди:
1) Начало = Конец + 1 и очередь пуста (рис. а);
2) Начало = Конец + 1 и очередь полна (рис. б).
Простое решение проблемы:
введение дополнительной переменной, идентифицирующей состояние очереди, а именно переменной Длина: 0..n+1.
Длина = текущее количество элементов в очереди.
Для пустой очереди Длина = 0.
Для полной очереди Длина = n+1.
Нерекурсивные процедуры обхода бинарных деревьев. (Лек 5.2)
В стеке S хранятся упорядоченные пары (p, n),
где p узел бинарного дерева, а n номер операции, которую надо применить к p, когда пара (p, n) будет выбрана из стека.
Операции
«посетить корень»,
«пройти левое поддерево»,
«пройти правое поддерево»
нумеруются числами 1, 2, 3 в зависимости от порядка их выполнения в данном варианте обхода.
В алгоритме:
посетить корень – посетить (p);
пройти левое поддерево if not Null (Left (p))
then S (Left (p), 1);
пройти правое поддерево if not Null (Right (p))
then S (Right (p), 1).
Для краткости использованы следующие обозначения операций со стеком:
S e вместо S := Push (e, S)
e S вместо Pop2 (e, S).
Общий алгоритм
void обход (BTree b)
{ Stack <(BTree, operation) > S ;
BTree p;
operation op ; // 1..3
S = Create; S (b, 1);
while ( !Null (S)) {
(p, op) S;
if (op == 1) {S (p, 2); операция 1; }
else if (op == 2) {S (p, 3); операция 2;}
else операция 3; //op == 3
} //end-while
} //обход
Выполнение процедуры обход (b)
Операции со стеком:
(b, 1);
(b, 1); (b, 2); {начало Опер1}… …{конец Опер1}
(b, 2); (b, 3); {начало Опер2}… …{конец Опер2}
(b, 3); {начало Опер3}… …{конец Опер3}
КЛП Операция 1 – посетить (p);
Операция 2 if ( !Null (Left (p))) S (Left (p), 1);
Операция 3 if ( !Null (Right (p))) S (Right (p), 1);
(b, 1);
(b, 1); (b, 2); посетить (p);
(b, 2); (b, 3); if ( !Null (Left (p))) (Left (p), 1); (Left (p), 1); …;
(b, 3); if ( !Null (Right (p))) (Right (p), 1);
(Right (p), 1);…;
,
void обход_ЛКП (BTree b) // обратный |
{ Stack <(BTree, operation)> S; |
BTree p; operation op ; // =1..2 |
S = Create; S (b , 1); |
while ( !Null (S)) { |
(p, op) S; |
if (op==1){S(p, 2); if (!Null (Left (p))) S(Left (p), 1);} |
else //op=2 |
{посетить (p); |
if (!Null (Right (p))) S (Right (p), 1) |
} |
} //end-while |
} // обход_ЛКП |
Бинарные деревья с размеченными листьями («комбинации»). Пример соответствия (для n = 4): Лес, Бинарное дерево, Комбинация, Скобки, Рукопожатия. (1 Лекция 05 3 БинДерРазмЛист.doc)
Задача кодирования (сжатия) сообщений. Префиксный код. Критерий оптимальности кода. Аналогия с задачами поиска и слияния упорядоченных списков. (Лек 6)
Префиксный код. Неравенство Крафта. (Лек 6)
Сложность алгоритма Хаффмана. (Лек 6)