Сибирский университет потребительской кооперации
Опубликован: 04.05.2005 | Доступ: свободный | Студентов: 4321 / 1347 | Оценка: 4.45 / 4.22 | Длительность: 12:28:00
ISBN: 978-5-9556-0034-5
Лекция 10:

Деревья

< Лекция 9 || Лекция 10: 12345 || Лекция 11 >

Пример. Напишем предикат, подсчитывающий общее количество вершин дерева. У него будет два параметра. Первый (входной) параметр - дерево, второй (выходной) - количество вершин в дереве.

Как всегда, пользуемся рекурсией. Базис: в пустом дереве количество вершин равно нулю. Шаг рекурсии: чтобы посчитать количество вершин дерева, нужно посчитать количество вершин в левом и правом поддереве, сложить полученные числа и добавить к результату единицу (посчитать корень дерева ).

Пишем:

tree_length (empty,0). /* В пустом дереве
                  нет вершин */
tree_length(tr(_,L,R),N):-
        tree_length (L,N1), 
            /* N1 - число вершин 
             левого поддерева */
        tree_length (R,N2), 
            /* N2 - число вершин 
             правого поддерева */
        N=N1+N2+1. /* число вершин 
              исходного дерева 
              получается сложением 
              N1, N2 и единицы */

Пример. Решим еще одну подобную задачу. Разработаем предикат, подсчитывающий не общее количество вершин дерева, а только количество листьев, т.е. вершин, не имеющих сыновей. Предикат будет иметь два параметра. Входной - исходное дерево, выходной - количество листьев дерева, находящегося в первом параметре.

Понятно, что, так как в пустом дереве нет вершин, в нем нет и вершин, являющихся листьями. Это первый базис рекурсии. Второй базис будет заключаться в очевидном факте, что дерево, состоящее из одной вершины, имеет ровно один лист. Шаг: для того, чтобы посчитать количество листьев дерева, нужно просто сложить количество листьев в левом и правом поддереве.

Запишем:

tree_leaves(empty,0). /* в пустом дереве
                  листьев нет */
tree_leaves(tr(_,empty,empty),1):-!. 
          /* в дереве с одним корнем - 
            один лист */
tree_leaves(tr(_,L,R),N):-
        tree_leaves(L,N1), 
          /* N1 - количество листьев 
            в левом поддереве */
        tree_leaves(R,N2), 
          /* N2 - количество листьев 
            в правом поддереве */
        N=N1+N2.

Пример. Создадим предикат, находящий сумму чисел, расположенных в вершинах дерева. Он будет иметь два аргумента. Первый - исходный список, второй - сумма чисел, находящихся в вершинах дерева, расположенного в первом аргументе.

Идея реализации будет очень простой и немного похожей на подсчет количества вершин. Базис рекурсии: сумма элементов пустого дерева равна нулю, потому что в пустом дереве нет элементов. Чтобы подсчитать сумму значений, находящихся в вершинах непустого дерева, нужно сложить сумму элементов, хранящихся в левом и правом поддереве, и не забыть добавить корневое значение.

На Прологе это записывается следующим образом:

tree_sum (empty,0). /* В пустом дереве
                  вершин нет */
tree_sum(tr(X,L,R),N):-
       tree_sum (L,N1), 
           /* N1 - сумма элементов 
            левого поддерева */
       tree_sum (R,N2), 
           /* N2 - сумма элементов 
            правого поддерева */
       N=N1+N2+X. /* складываем N1, N2 
             и корневое значение */

Пример. Создадим предикат, позволяющий вычислить высоту дерева. Напомним, что высота дерева - это наибольшая длина пути от корня дерева до его листа. Предикат будет иметь два параметра. Первый (входной) - дерево, второй (выходной) - высота дерева, помещенного в первый параметр.

Базис рекурсии будет основан на том, что высота пустого дерева равна нулю. Шаг рекурсии - на том, что для подсчета высоты всего дерева нужно найти высоты левого и правого поддеревьев, взять их максимум и добавить единицу (учесть уровень, на котором находится корень дерева ). Предикат max (или max2 ), вычисляющий максимум из двух элементов, был разработан нами еще в третьей лекции. Мы воспользуемся им при вычислении высоты дерева.

Получается следующее.

tree_height(empty,0). /* Высота пустого 
          дерева равна нулю */
tree_height(tr(_,L,R),D) :- 
        tree_height(L,D1), 
         /* D1 - высота левого 
               поддерева */ 
        tree_height(R,D2), 
         /* D2 - высота правого
               поддерева */
        max(D1,D2,D_M), 
         /* D_M - максимум из высот 
          левого и правого поддеревьев */
        D=D_M+1. 
         /* D - высота дерева получается 
          путем увеличения числа D_M 
          на единицу*/

Существует особый вид бинарных деревьев - так называемые двоичные справочники. В двоичном справочнике все значения, входящие в левое поддерево, меньше значения, находящегося в корне, а все значения, расположенные в вершинах правого поддерева, больше корневого значения, а левое и правое поддеревья, в свою очередь, также являются двоичными справочниками. Такие деревья еще называют упорядоченными слева направо.

Пример. Усовершенствуем предикат tree_member для проверки принадлежности значения двоичному справочнику. Повысить эффективность этого предиката мы сможем, воспользовавшись тем, что в двоичном справочнике если искомое значение не совпадает с тем, которое хранится в корне, то его имеет смысл искать только в левом поддереве, если оно меньше корневого, и, соответственно, только в правом поддереве, если оно больше корневого значения.

Модифицированный предикат будет выглядеть следующим образом:

tree_member2(X,tr(X,_,_)):-!. /* X - корень
                   дерева */
tree_member2(X,tr(K,L,_)):-
        X<K,!,
        tree_member2(X,L). 
           /* X - принадлежит 
            левому поддереву */
tree_member2(X,tr(K,_,R)):-
        X>K,!,
        tree_member2(X,R). 
           /* X - принадлежит 
            правому поддереву */
< Лекция 9 || Лекция 10: 12345 || Лекция 11 >
Виктор Бондарь
Виктор Бондарь

После приведения формулы вида ПНФ к виду ССФ вы получаете формулу, в безквантовой матрице которой дизъюнкт содержит оба контранрных атома:. Как тогда проводить его унификацию, если в случае замены x на f(x) весь дизъюнкт обратится в единицу?

Ольга Потапенко
Ольга Потапенко

никак не могу увидеть тексты самих лекций.