Деревья
Упражнение 1. Определите предикат, который проверяет принадлежность элемента двоичному дереву.
Двоичное дерево поиска — это конечное корневое дерево, в котором элементы левого поддерева любой вершины меньше этой вершины, а элементы правого поддерева не меньше нее. На рис. 9.2 приведен пример двоичного дерева поиска.
В следующей программе генерируется случайным образом двоичное дерево поиска с вершинами, в которых хранятся целые неотрицательные числа, а также реализуются операции над двоичными деревьями.
Предикат insert/2 вставляет элемент в двоичное дерево поиска так, чтобы оно оставалось деревом поиска. Предикат get_nd/2 недетерминированно возвращает вершины заданного уровня. Предикат height/1 возвращает высоту дерева, предикат height_nd/2 недетерминированно возвращает высоту ветвей дерева. Высота дерева определяется как максимальная из высот ветвей. Предикаты sum/1 и count/1 вычисляют соответственно сумму элементов дерева и количество четных вершин. В подсчетах используются накопители. Предикат replace/3 заменяет элементы дерева с заданным значением другими элементами.
domains binTree{Elem} = bt(binTree{Elem}, Elem, binTree{Elem}); leaf. class predicates % построение дерева предков createBinTree: (unsigned, positive) -> binTree{unsigned}. createBinTree: (unsigned, positive, binTree{unsigned}) -> binTree{unsigned}. insert: (Elem, binTree{Elem}) -> binTree{Elem}. clauses createBinTree(R, N) = createBinTree(R, N, leaf). createBinTree(_, 0, Tree) = Tree:- !. createBinTree(R, N, Tree) = createBinTree(R, N - 1, insert(math::random(R), Tree)). insert(X, leaf) = bt(leaf, X, leaf). insert(X, bt(LTree, Y, RTree)) = bt(insert(X, LTree), Y, RTree):- X < Y, !. insert(X, bt(LTree, Y, RTree)) = bt(LTree, Y, insert(X, RTree)). class predicates print: (binTree{Elem}). print: (binTree{Elem}, charCount). clauses print(BinTree):- print(BinTree, 0). print(leaf, _). print(bt(LeftTree, Elem, RightTree), N):- print(LeftTree, N + 1), write(string::create(N, "\t"), Elem), nl, print(RightTree, N + 1). class predicates % вершины заданного уровня get_nd: (binTree{Elem}, positive) -> Elem nondeterm. clauses get_nd(bt(_, A, _), 0) = A:- !. get_nd(bt(LTree, _, _), N) = get_nd(LTree, N - 1). get_nd(bt(_, _, RTree), N) = get_nd(RTree, N - 1). class predicates % высота дерева height: (binTree{Elem}) -> integer. height_nd: (binTree{Elem}, integer) -> integer nondeterm. clauses height(Tree) = list::maximum([N || N = height_nd(Tree, -1)]). height_nd(leaf, N) = N. height_nd(bt(LTree, _, _), N) = height_nd(LTree, N + 1). height_nd(bt(_, _, RTree), N) = height_nd(RTree, N + 1). class predicates % подсчеты sum: (binTree{unsigned}) -> unsigned. sum: (binTree{unsigned}, unsigned) -> unsigned. count: (binTree{unsigned}) -> positive. count: (binTree{unsigned}, positive) -> positive. clauses sum(Tree) = sum(Tree, 0). % сумма всех вершин sum(leaf, N) = N. sum(bt(LTree, A, RTree), N) = sum(RTree, sum(LTree, N) + A). count(Tree) = count(Tree, 0). % количество четных вершин count(leaf, N) = N. count(bt(LTr, A, RTr), N) = count(RTr, count(LTr, N) + C):- C = if A mod 2 = 0 then 1 else 0 end if. class predicates % замена заданных вершин replace: (binTree{unsigned}, unsigned, unsigned) -> binTree{unsigned}. clauses replace(leaf, _, _) = leaf. replace(bt(LTree, V, RTree), A, B) = bt(replace(LTree, A, B), C, replace(RTree, A, B)):- C = if V = A then B else V end if. run():- Tree = createBinTree(20, 20), print(Tree), write("\n\nПоколение 3: ", [Elem || Elem = get_nd(Tree, 3)]), write("\nВысота дерева: ", height(Tree)), write("\nСумма элементов дерева: ", sum(Tree)), write("\nКоличество четных вершин дерева: ", count(Tree)), write("\nЗамена нулевых элементов на 100:\n\n"), Tree1 = replace(Tree, 0, 100), print(Tree1), _ = readLine().Пример 9.3. Двоичное дерево поиска
Предикат maximum возвращает максимальный элемент списка.