Деревья
Настоящая глава посвящена конечным корневым деревьям — бинарным деревьям и деревьям произвольного вида. Деревья представляются в виде термов. Домены этих термов определяются рекурсивно. В качестве доменов деревьев используются полиморфные домены.
Примером дерева первого вида является дерево предков человека, а примером дерева второго вида — дерево потомков (рис. 9.1).
В директории Exe проекта следует создать текстовый файл fam.txt и поместить в него приведенные ниже факты (листинг 9.1).
clauses parent("Иван", "Мария"). parent ("Анна", "Мария"). parent ("Мария", "Павел"). parent ("Мария", "Петр"). parent ("Мария", "Елизавета"). parent ("Петр", "Степан"). male("Иван"). male("Степан"). male("Петр"). male("Павел"). female("Мария"). female("Анна"). female("Елизавета").Пример 9.1. Файл fam.txt. База данных
9.1. Двоичное дерево
Двоичное, или бинарное, дерево — это конечное корневое дерево, каждая вершина которого имеет не более двух "сыновей". Пример двоичного дерева приведен на рис. 9.1 (a).
Полиморфный домен двоичных деревьев определяется рекурсивно в виде:
domains binTree{Elem} = bt(binTree{Elem}, Elem, binTree{Elem}); leaf.
Имена доменов левого и правого поддеревьев совпадают с именем самого домена деревьев.
В следующей программе рекурсивно строится дерево предков человека (предикат createAncTree/1), оно выводится на печать (предикат print/1), при этом корень располагается слева, левое поддерево находится выше корня, а правое поддерево — ниже. Строится список вершин дерева. Предикат get_nd/1 недетерминированно возвращает вершины дерева.
class facts - rel parent: (string Родитель, string Ребенок). male: (string). female: (string). domains binTree{Elem} = bt(binTree{Elem}, Elem, binTree{Elem}); leaf. class predicates % построение дерева предков createAncTree: (string Name) -> binTree{string}. createTree1: (string Name) -> binTree{string}. createTree2: (string Name) -> binTree{string}. clauses createAncTree(X) = bt(createTree1(X), X, createTree2(X)). createTree1(X) = createAncTree(Y):- parent(Y, X), male(Y), !. createTree1(_) = leaf. createTree2(X) = createAncTree(Y):- parent(Y, X), female(Y), !. createTree2(_) = leaf. class predicates % обход дерева get_nd: (binTree{Elem}) -> Elem nondeterm. clauses get_nd(bt(_, A, _)) = A. get_nd(bt(LeftTree, _, _)) = get_nd(LeftTree). get_nd(bt(_, _, RightTree)) = get_nd(RightTree). 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). run():- file::consult("fam.txt", rel), Tree = createAncTree("Степан"), print(Tree), nl, write([Elem || Elem = get_nd(Tree)]), _ = readLine().Пример 9.2. Дерево предков
Предикат create создает строку, состоящую из заданного количества символов, с помощью повторения указанной последовательности символов.