Question

I want to write a program in Prolog that builds a list of all the even integers that reside in a b-tree. This is what I've written so far. A predicate that counts all the elements in the tree. I don't know where to scratch.

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).

Thanks a lot.

Was it helpful?

Solution

Dunno anything about Visual Prolog, but in normal Prolog, I'd do something like the following...

First, I'd denote an empty btree as the atom btree and represent a non-empty btree as a structure of arity 3, thus:

btree( Payload, LeftChildren, RightChildren )

where Payload is the data for the node (an integer apparently), with LeftChildren and RightChildren being the btrees representing, respectively, the left and right children of the current node.

Traversing the tree to count those nodes with even-valued nodes is simple. The public predicate has arity 2, accepting the [bound] btree structure to be examined, and a bound or unbound value representing the count of even items. It calls an internal, recursive "helper" predicate that walks a tree and develops the count.

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

The internal predicate is simple as well. Having arity 3, the first argument is the tree to be examined, the second is an accumulator and the third is the final count (which won't be unified until the very end). There are two possible cases.

  1. If the tree is empty, we have the final count:

    count_even( btree , N , N ) .
    
  2. If the tree is non-empty, we examine the current node, then recursively walk the left and right child trees, thusly:

    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  )
      .
    

We also need a trivial helper to tell us whether a particular value is even or odd:

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

It should be noted that the data structure you're using is not a b-tree, per se: it is a binary tree.

B-trees are something of a generalization of a height-balanced binary tree optimized for disk storage. Each node has a variable number of keys and a variable number of children (corresponding to the number of keys). For more information, see

Here's a picture of a B-tree:

B-Tree Visualization

And a picture of a binary tree:

Binary Tree Visualization

OTHER TIPS

You have to check every node to see if it's even or odd and only count the ones that are even. A simple modification to your program should do (however I'd do it a bit different):

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.

I just count 1 - Number mod 2 which is 1 when the number is even and 0 otherwise.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top