Подсчет всех четных целых чисел в b-дереве в Прологе - PullRequest
0 голосов
/ 04 января 2012

Я хочу написать программу на Прологе, которая создает список всех четных целых чисел, которые находятся в b-дереве.Это то, что я написал до сих пор.Предикат, который считает все элементы в дереве.Я не знаю, где поцарапать.

Domains
element=integer
tree=a(tree,element,tree);void
    list=integer*

Predicates
     nondeterm count(tree,element)
     nondeterm count_even(tree,list)

Clauses
    count(a(void,Number,void),1).
count(a(Esq,_,Dreta),Counter) :-
    count(Esq,Counter1),
    count(Dreta,Counter2),
    Counter=Counter1+Counter2+1.

Goal
       count(a(a(void,1,void),5,a(a(void,4,void),1,a(void,4,void))),N).

Большое спасибо.

Ответы [ 2 ]

1 голос
/ 04 января 2012

Не знаю ничего о Visual Prolog, но в обычном Прологе я бы сделал что-то вроде следующего ...

Во-первых, я бы обозначил пустое дерево как атом btree и представлял бы не- пустое btree как структура арности 3, таким образом:

btree( Payload, LeftChildren, RightChildren )

, где Payload - данные для узла (очевидно, целое число), с LeftChildren и RightChildren, представляющими btrees,соответственно левый и правый дочерние узлы текущего узла.

Обход дерева для подсчета этих узлов с четными узлами прост.Открытый предикат имеет арность 2, принимая структуру [bound] btree, которую нужно исследовать, и привязанное или несвязанное значение, представляющее количество четных элементов.Он вызывает внутренний рекурсивный предикат-помощник, который обходит дерево и вырабатывает счет.

count_even( T , N ) :- count_even( T , 0 , N ) .

Внутренний предикат также прост.Имея арность 3, первый аргумент - это дерево, которое нужно исследовать, второй - накопитель, а третий - окончательный счет (который не будет объединен до самого конца).Есть два возможных случая.

  1. Если дерево пустое, у нас есть окончательный счет:

    count_even( btree , N , N ) .
    
  2. Если дерево не-empty, мы исследуем текущий узел, затем рекурсивно обходим левые и правые дочерние деревья, таким образом:

    count_even( btree( V , L , R ) , T , N ) :-
      is_even( V , X ) ,
      T1 is T+X ,
      count_even( L , T1 , T2 ) ,
      count_even( R , T2 , N  )
      .
    

Нам также нужен тривиальный помощник, чтобы сказать нам, является ли конкретное значениечетное или нечетное:

is_even( V , 1 ) :- 0 is V mod 2 , ! .
is_even( V , 0 ) .

Следует отметить, что используемая вами структура данных не является b-деревом, per se : это двоичное дерево .

B-деревья представляют собой обобщение двоичного дерева с сбалансированной высотой, оптимизированного для хранения на диске.Каждый узел имеет переменное количество ключей и переменное количество дочерних элементов (соответствующее количеству ключей).Для получения дополнительной информации см.

Вот изображение B-дерево:

B-Tree Visualization

и изображение двоичного дерева:

Binary Tree Visualization

0 голосов
/ 04 января 2012

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

element=integer
tree=a(tree,element,tree);void
    list=integer*

Predicates
     nondeterm count_even(tree,list)

Clauses
    count_even(a(void,Number,void),Value):-
      Value = 1 - Number mod 2.
count_even(a(Esq,Number,Dreta),Counter) :-
    count_even(Esq,Counter1),
    count_even(Dreta,Counter2),
    count_even=Counter1 + Counter2 + 1 - Number mod 2.

Я просто считаю 1 - Number mod 2, который равен 1, когда число четное, и 0, в противном случае.

...