Re: [boost] A generic tree manipulation library

2003-03-24 Thread Reece Dunn
Darren Cook wrote:

I'm using new/delete currently, but was planning to use boost.Pool once my 
design has settled down.
I was considering using some sort of pooling/block allocation method to 
improve allocation efficiency, but was leaving that as an optimization 
consideration for when I got the design sorted.

A std::map would be too much overhead for my particular application (which 
tends to have deep trees with few branches).
I'm aware of that. I used a std::map to show an example implementation 
without worrying about the actual details.

I was also planning to write an implementation of the tree_node interface 
for an n-ary tree; something like:

template< typename T, long n >
class nary_tree_node
{
  public:
 typedef nary_tree_node * node_pointer;
 typedef nary_tree_node * iterator;
  private:
 node_pointer nodes[ n ];
 T data;
  public:
 inline iterator first_child()
 {
return( nodes );
 }
 inline iterator last_child()
 {
return( nodes + n );
 }
  public:
 inline iterator operator[]( index_type it )
 {
// range checks?
// compatible index type??
return( nodes[ it ]);
 }
};
The other methods and typedefs would be implemented to be consistent with 
the other implementation. This was the idea: you can supply your own 
implementation or use one of the tree node implementations provided.

Since you are using a binary tree node type, you can use something like:

typedef nary_tree_node< std::string, 2 > binary_node;

Finding the previous sibling or parent in my tree requires starting from 
the root node (or keeping a stack of nodes visited).
Would it be more efficient to have a pointer to the parent node as well? 
This would allow you to move up to the parent and then along to the next 
node without having to start again from the root.

Do you have any example usage?
The trie class is an example of how to use the tree class and I have a test 
program for this, but I do not have any other examples at the moment.

I wonder if it would be better to approach this from the 
algorithms/iterators side and come to the containers later? I.e. what 
operations do you need to do on the trees?
That is a good suggestion.

There should be an iterator for the tree node that will iterate along the 
siblings; this has already been accounted for. I was also thinking about 
extending this iterator to provide "up" and "down" iterator types to move up 
to the parent and down to the first child. I use the names up and down so 
that the types could be used in other 2D iterator types.

The tree should provide several navigational iterators:
[1] inorder_iterator: for in order traversal;
[2] preorder_iterator: for pre-order traversal;
[3] postorder_iterator: for post-order traversal;
[4] iterator: for navigating along the leaf nodes inorder.
There may be others that I have not thought of. As for the algorithms that 
are to be supported, there are several points:

[1]  It should be easy to use the standard algorithms with the tree 
implementation wherever possible, e.g.

std::for_each(
  tree.inorder_begin(),
  tree.inorder_end(),
  ...
);
Could it be possible to use iterator adaptors like are used for containers 
and the functors (with binder1st, etc.)?

As a couple of examples I need:
  1. for_each() of first child at each node.
  2. display all node values in the tree on stdout.
This may be possible through iterator adaptors:

std::for_each(
  tl::iter::first_child( tree.preorder_begin()),
  tl::iter::first_child( tree.preorder_end()),
  ...
);
std::for_each(
  tl::iter::indentor( tree.preorder_begin()),
  tl::iter::indentor( tree.preorder_end()),
  ...
);
NOTE: This is experimental at the moment. I do not have an implemetnation of 
the above, it is just a preliminary look at a possible solution to the above 
problem.

The idea for the indentor is to keep a track of the level that the iterator 
is on in the depth of the tree, and provide an output method something along 
the lines of:
  indent according to level
  output the data to the output stream

I have an implementation of some indentation technology that I have used for 
my own tracing functionality. I am looking at submitting that to the boost 
mailing list later this week (both the indentation stuff and the tracing 
stuff), I just need to prepare it for submission.

[2] There should be specializations of the standard algorithms to provide 
proper integration with the STL. The most noticable example of this would be 
std::swap.

[3] There should be a whole set of algorithms that are designed to fit in 
with a tree structure. An example would me tl::mirror to transform a tree to 
the mirror image of itself.

-

There should be the ability to construct a tree from another tree (copying 
the entire tree) or constructing it from a tree node (making that node the 
root of the new tree).

BTW, I'm new to Boost. Is it normal to include all the Allocator stuff 
early on when discussi

Re: [boost] A generic tree manipulation library

2003-03-23 Thread Darren Cook
I'm very interested in having tree container concepts in Boost. 

The tree_node_map class provides an implementation to a basic tree node 
of variable branching size. The implementation here uses the std::map to 
implement the children, but this could equally be a std::list, 
std::vector or any suitable container; it could even be a low-level 
implementation (for performance) or a fixed-size array (for n-ary nodes).
I've been implementing a tree class recently where each node has:
  Node* first_child;
  Node* next_sibling;
I'm using new/delete currently, but was planning to use boost.Pool once my 
design has settled down.

A std::map would be too much overhead for my particular application (which 
tends to have deep trees with few branches).

I briefly played with one block of memory per branch and doing away with the 
first_child pointer, but decided to come back to that idea later. It has a 
problem with identifying the last node; either you need to store "branch 
length", or a flag to mark the end (in which case you've saved no memory; 
still may have a speed advantage however).

Finding the previous sibling or parent in my tree requires starting from the 
root node (or keeping a stack of nodes visited).

The tree class is just a wrapper around a tree node that provides access 
to a root element. This would need some major work and additional 
support (e.g. post/pre/in-order traversal iterators) if it were to be 
useful.
Do you have any example usage?

I wonder if it would be better to approach this from the 
algorithms/iterators side and come to the containers later? I.e. what 
operations do you need to do on the trees?

As a couple of examples I need:
 1. for_each() of first child at each node.
 2. display all node values in the tree on stdout.
I'm not yet clear what I want from the second option there. Some kind of 
indenting I guess.

BTW, I'm new to Boost. Is it normal to include all the Allocator stuff early 
on when discussing designs? I thought it would be grafted on at the end.

Darren

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] A generic tree manipulation library

2003-03-21 Thread Reece Dunn
Rene Rivera wrote:

I'm very interested in having tree container concepts in Boost. It's my 
plan
to submit such a thing to Boost in the summer. Currently I only have a
rank_tree implementation (log2 n, or better on all ops) so having someone
else work on other types of tree implementations would be awsome ;-)
I'd be happy to share ideas. I have included the implementation that I was 
referring to in the previous e-mail. I know that it needs a lot of work if 
it were to be submitted to boost, but I just wanted to gague reactions 
before I did any major work to it.

The tree_node_map class provides an implementation to a basic tree node of 
variable branching size. The implementation here uses the std::map to 
implement the children, but this could equally be a std::list, std::vector 
or any suitable container; it could even be a low-level implementation (for 
performance) or a fixed-size array (for n-ary nodes).

The tree class is just a wrapper around a tree node that provides access to 
a root element. This would need some major work and additional support (e.g. 
post/pre/in-order traversal iterators) if it were to be useful.

The trie class is an application of the tree class that provides operations 
for adding and looking for items in an associative container-like way. There 
is a bug with the word count (it does not track with std::map<>::size() on 
the same data).

The trie class operates on a key that is a sequence of elements. If the key 
is std::string, then the trie class will construct the tree operating on 
characters as lookup for the child nodes, e.g.

*-h-e-l-l-o-$ /-$
+-w-o-r-l-d--+-s-$
This is useful for associative lookup in two ways:
*  it should provide faster lookup than a std::map because it is iterating 
through the key as it moves down the list, therefore it does not need to 
recompare the strings every time it moves around the tree (unlike the 
red-black binary tree used in most std::map implementations)
*  it stores the strings in a compressed form (although this benefit is 
removed by the need for the space to store the tree structure)

The lookup function for the trie class will add an item if the key is not 
currently in the trie structure, whereas find will not. Both operate on a 
first to last iterator principle.

I hope this helps with your submission in the Summer. If you want we could 
combine forces to develop the library.

-rhd-

_
It's fast, it's easy and it's free. Get MSN Messenger today! 
http://messenger.msn.co.uk
#ifndef __STL__TRIE
#define __STL__TRIE
#  include 
#  include 
#  include 
#  define null NULL
  

  namespace stl
  {
 template< typename T, typename Index = int, class Allocator = 
std::allocator< T > >
 class tree_node_map
 {
public:
   typedef T   value_type;
   typedef Allocator   
allocator_type;
   typedef Index   index_type;
public:
   typedef typename Allocator::template rebind< T >::other
   
value_allocator;
public:
   typedef typename value_allocator::reference reference;
   typedef typename value_allocator::const_reference   
const_reference;
   typedef typename value_allocator::pointer   pointer;
   typedef typename value_allocator::const_pointer 
const_pointer;
public:
   typedef typename value_allocator::size_type size_type;
   typedef typename value_allocator::difference_type   
difference_type;
public:
   typedef std::map< index_type, tree_node_map * > 
child_container;
public:
   class iterator
   {
  friend class tree_node_map;
  private:
 typename child_container::iterator node;
  public:
 inline iterator & operator++()
 {
++node;
return( *this );
 }
 inline iterator & operator--()
 {
--node;
return( *this );
 }
  public:
 inline typename tree_node_map & operator*()
 {
return( *( node -> second ));
 }
 inline typename tree_node_map * operator->()
 {
return( node -> second );
 }
  public:
 inline bool operator==( const iterator & i )
 {
return( node == i.node );
 }
 inline bool operator!=( const iterator & i )
 {
return( n

Re: [boost] A generic tree manipulation library

2003-03-15 Thread Rene Rivera
[2003-03-15] Reece Dunn wrote:

>Is there a library in boost that allows the manipulation of n-ary trees 
>(including binary trees and arbitary branching trees as subsets of this).

No. But there was some previous discussion about Kasper Peeters tree
implementation...  

http://lists.boost.org/MailArchives/boost/msg36876.php
Boost Mailing List Archive -- [boost] any interest in a 'tree' container?

I'm very interested in having tree container concepts in Boost. It's my plan
to submit such a thing to Boost in the summer. Currently I only have a
rank_tree implementation (log2 n, or better on all ops) so having someone
else work on other types of tree implementations would be awsome ;-)

>If so, does this have support for trie structures (a dictionary-like object 
>where each level of the tree represents the nth letter in a word contained 
>in it).

Haven't seen such a proposal here, yet. Along those same lines I also have a
specialized version of a trie container, hex_part_dictionary, which stores
nibles at each level of tree. But it would require a complete rewrite to be
usefull to anyone, even to myself ;-\

>Also, how do the iterators work? Is there a concept of moving across the 
>siblings and moving up/down the tree?
>
>I have had a few ideas about implementing a library along these lines if 
>none already exists. The idea is to add a new set of iterator categories:
>   up_iterator --> has a function up() that moves the iterator *up* the 
>container (in a kind of 2D space).
>   down_iterator --> has a function down() to move the iterator *down* the 
>container.
>   updown_iterator --> has both an up() and down() function for moving 
>across the y-axis of the container (like what the bidirectional_iterator is 
>to the forward_iterator)

My equivalent idea was to introduce a "cursor" concept that has all the
various tree navigation operations. It would return clasic linear iterators
for some things, like the children of the current node. Here are some ops
for such a cursor: parent(), children(), rchildren(), left_children(),
left_rchildren(), right_children(), right_rchildren(), etc. It then becomes
very easy to write classical traversal algos in a generic form.

>Will it be better just to have the down and the updown iterators so it is 
>more like the forward and bidirectional iterators? 

I'm of the opinion that the closer a tree container interface is to the
standard linear iterators the less usefull it becomes as a tree structure.

>Can these types be added 
>to other 2D-like containers (vector2d anyone???)
>
>The idea is to have general requirements for what constitutes a *tree node* 
>that allows them to be manipulated and accessed in a common way - whether
it 
>is a binary tree node, an n-ary tree node using an array or an arbitary 
>branching node using a linked list for siblings.
>
>There is plans to have a tree class that uses an implementation of a tree 
>node, giving access to the root of the tree and possibly additional stuff.
>
>The tree class can then be used to implement a trie data structure,
possibly 
>as a trie_map (using the associative container interface to give the 
>container very fast lookup) or as a seperate class that is used to
implement 
>trie_map, trie_multimap, trie_set and trie_multiset containers.

Given the variety of ways to implement trees, both in storage and behaviour,
I would lean towards making a generic tree concept that gets implemented by
the variety of trees. As opposed to using a generic tree implementation to
store other types of trees. This is because many of the tree implementations
get their advantages from very special storage to improve speed. For example
my hex_part_dictionary stores only 4bits of the data at each level to reduce
the size of nodes and to reduce the single level branching to fit in a 16bit
field. I need to be that efficient because I need to literally store a
dictionary, as in something like Oxford English.

Other things I've thought about include:

* Having both functional and iterator versions of traversals. For example
having both: inorder_traversal_iterator class, and inorder_traversal
algorithm. The iterator would be constructed from a cursor and the algorithm
would take a cursor and visitor function.

...I had others, but they escape me right at this moment :-( ...


-- grafik - Don't Assume Anything
-- [EMAIL PROTECTED] - [EMAIL PROTECTED]
-- [EMAIL PROTECTED]
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


[boost] A generic tree manipulation library

2003-03-15 Thread Reece Dunn
Is there a library in boost that allows the manipulation of n-ary trees 
(including binary trees and arbitary branching trees as subsets of this).

If so, does this have support for trie structures (a dictionary-like object 
where each level of the tree represents the nth letter in a word contained 
in it).

Also, how do the iterators work? Is there a concept of moving across the 
siblings and moving up/down the tree?

I have had a few ideas about implementing a library along these lines if 
none already exists. The idea is to add a new set of iterator categories:
  up_iterator --> has a function up() that moves the iterator *up* the 
container (in a kind of 2D space).
  down_iterator --> has a function down() to move the iterator *down* the 
container.
  updown_iterator --> has both an up() and down() function for moving 
across the y-axis of the container (like what the bidirectional_iterator is 
to the forward_iterator)

Will it be better just to have the down and the updown iterators so it is 
more like the forward and bidirectional iterators? Can these types be added 
to other 2D-like containers (vector2d anyone???)

The idea is to have general requirements for what constitutes a *tree node* 
that allows them to be manipulated and accessed in a common way - whether it 
is a binary tree node, an n-ary tree node using an array or an arbitary 
branching node using a linked list for siblings.

There is plans to have a tree class that uses an implementation of a tree 
node, giving access to the root of the tree and possibly additional stuff.

The tree class can then be used to implement a trie data structure, possibly 
as a trie_map (using the associative container interface to give the 
container very fast lookup) or as a seperate class that is used to implement 
trie_map, trie_multimap, trie_set and trie_multiset containers.

Feedback would be greatly appreciated,
  Reece H Dunn
-rhd-
mailto:[EMAIL PROTECTED]


_
MSN Messenger - fast, easy and FREE! http://messenger.msn.co.uk
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost