Скачать презентацию Сошников Дмитрий Валерьевич к ф -м н Скачать презентацию Сошников Дмитрий Валерьевич к ф -м н

3749e35e35795ef605883b84964377c9.ppt

  • Количество слайдов: 16

Сошников Дмитрий Валерьевич к. ф. -м. н. , доцент dmitryso@microsoft. com Функциональное программирование Факультет Сошников Дмитрий Валерьевич к. ф. -м. н. , доцент dmitryso@microsoft. com Функциональное программирование Факультет инноваций и высоких технологий Московский физико-технический институт

Лекция 13 Деревья выражений и деревья поиска. Продолжения 2 Лекция 13 Деревья выражений и деревья поиска. Продолжения 2

 © 2008 Сошников Д. В. Дерево поиска типа T, на котором определен полный © 2008 Сошников Д. В. Дерево поиска типа T, на котором определен полный порядок < - это двоичное дерево, для каждой вершины x которого Все вершины левого поддерева меньше х Все вершины правого поддерева больше х 6 3 1 7 4 3

© 2008 Сошников Д. В. Вставка элемента в дерево поиска let rec insert x © 2008 Сошников Д. В. Вставка элемента в дерево поиска let rec insert x t = match t with Nil -> Node(x, Nil) | Node(z, L, R) -> if z=x then t else if x insert x t) Nil L; ; 4

 Эффективность поиска зависит от конфигурации дерева поиска: 1 Худший вариант: O(n), 2 ▪ Эффективность поиска зависит от конфигурации дерева поиска: 1 Худший вариант: O(n), 2 ▪ list_to_tree [1; 2; 3; 4]; ; ▪ линейный поиск 3 Лучший вариант: O(log 2 n) ▪ сбалансированное дерево ▪ двоичный поиск © 2008 Сошников Д. В. Эффективность поиска 4 Древовидные алгоритмы поиска находятся посередине между двоичным и линейным поиском по эффективности поиска, но в них проще реализуется вставка элементов 5

© 2008 Сошников Д. В. Сортировка списка let tree_sort : int list -> int © 2008 Сошников Д. В. Сортировка списка let tree_sort : int list -> int list = list_to_tree >> tree_to_list; ; let tree_sort L = (list_to_tree >> tree_to_list) L; ; Указание «правильного» определения: let tree_sort = list_to_tree >> tree_to_list; ; на F# приводит к проблеме с выводом типов, называемой value restriction – для неявных аргументов компилятор не производит обобщение типов, и не может правильно определить generic type. Решение: в явном виде указать тип, или указать явный аргумент. 6

© 2008 Сошников Д. В. Деревья выражений Арифметические выражения с бинарными и унарными операциями © 2008 Сошников Д. В. Деревья выражений Арифметические выражения с бинарными и унарными операциями удобно представлять двоичными деревьями Можно использовать описанный ранее тип, или ввести более «прозрачный» type Expr. Tree = Op of char*Expr. Tree | Value of int; ; + let sample = Op('+', Op('*', Value(1), Value(2)), Value(3)); ; Здесь операция представляется char, но более правильно конечно использовать discriminated union (Enum) * 1 3 2 7

 © 2008 Сошников Д. В. Вычисление выражения Рекурсивный обход дерева, для каждого узла © 2008 Сошников Д. В. Вычисление выражения Рекурсивный обход дерева, для каждого узла – вычисление операции для левого и правого поддерева let rec compute = function Value(x) -> x | Op(op, L, R) -> match op with '+' -> compute L+compute | '-' -> compute L-compute | '*' -> compute L*compute | '/' -> compute L/compute R R; ; 8

 Простейший алгоритм грамматического разбора Метод рекурсивного спуска: система взаимно рекурсивных функций; каждая функция Простейший алгоритм грамматического разбора Метод рекурсивного спуска: система взаимно рекурсивных функций; каждая функция разбирает свой фрагмент дерева Функция разбора воспринимает входной поток символов, потребляет столько символов, сколько ей нужно © 2008 Сошников Д. В. Разбор выражения в дерево Используется подход с разностными списками: функция принимает на вход список символов, возвращает пару: остаток списка и дерево выражения 9

© 2008 Сошников Д. В. Префиксная форма let parse_infix expr = let rec ff © 2008 Сошников Д. В. Префиксная форма let parse_infix expr = let rec ff expr = match expr with [] -> failwith "Error" | h: : t when System. Char. Is. Digit(h) -> (t, Value(System. Int 32. Parse(h. To. String()))) | h: : t when h=' ' -> ff t | h: : t -> let (t 1, l) = ff t in let (t 2, r) = ff t 1 in (t 2, Op(h, l, r)) in snd (ff expr); ; parse_infix ['+'; '*'; '1'; '2'; '3']= Op ('+', Op ('*', Value 1, Value 2), Value 3) 10

© 2008 Сошников Д. В. Другие алгоритмы Разбор выражения в префиксной/инфиксной/постфиксной форме в дерево © 2008 Сошников Д. В. Другие алгоритмы Разбор выражения в префиксной/инфиксной/постфиксной форме в дерево Замена переменной на подвыражение (для этого расширить тип, добавив Var of char) Вычисление выражения в постфиксной форме (с деревом и без) Вычисление выражение в инфиксной форме без использования дерева 11

 © 2008 Сошников Д. В. Хвостовая рекурсия для деревьев? На первый взгляд хвостовая © 2008 Сошников Д. В. Хвостовая рекурсия для деревьев? На первый взгляд хвостовая рекурсия для деревьев невозможна нелинейная рекурсия не может быть сведена к итерации В императивных языках рекурсия сводится к итерации с помощью стека В стеке запоминаются «адреса возврата» и параметры В функциональном программировании можно использовать continuations (продолжения) 12

let size t = let rec size' t cont = match t with Nil let size t = let rec size' t cont = match t with Nil -> cont 0 | Node(_, L, R) -> size' L (fun x 1 -> size' R (fun x 2 -> cont(x 1+x 2+1))) in size' t (fun x->x); ; © 2008 Сошников Д. В. Определение размера дерева let rec size t = Nil -> 0 | Node(_, L, R) -> 1+size L+size R; ; Continuation – это явно передаваемая функция, указывающая, какие вычисления проводить после применения рекурсии Вместо рекурсивного вызова мы строим функцию, содержащую рекурсивный вызов Функции строятся не на стеке, а в куче (heap) -> избегаем переполнения стека Рекурсия действительно получается хвостовая! Дерево развертывается в последовательные вызовы функции 13

© 2008 Сошников Д. В. Улучшенный вариант let size t = let rec size' © 2008 Сошников Д. В. Улучшенный вариант let size t = let rec size' acc t cont = match t with Nil -> cont acc | Node(_, L, R) -> size' (1+acc) L (fun x -> size' x R cont) in size' 0 t (fun x->x); ; Используется сочетание аккумулятора с продолжением Аналогично использованию стека с циклом 14

ü © 2008 Сошников Д. В. Мораль Деревья не имеют непосредственной поддержки в библиотеке ü © 2008 Сошников Д. В. Мораль Деревья не имеют непосредственной поддержки в библиотеке языка Часто реализуются программистом с учетом ü ü ü особенностей задачи Два часто используемых варианта использования двоичных деревьев Деревья поиска Деревья выражений Деревья общего вида Файлы и директории Процессы, нити, . . . Типы данных, основанные на деревьях … 15

Вопросы? 16 Вопросы? 16