views:

203

answers:

6

I`m writing binary search tree template for two reasons - learning C++ and learning most common algorithms and data structures.
So, here is the question - as long as I want to implement iterators, it seems to me that there is no strict definition for where tree ends. What are your suggestions? How do I do this?

+9  A: 

For trees, there are standards for traversing the tree, i.e. enumerating the nodes: Preorder traversal, inorder traversal, and postorder traversal. Rather than describe all these here, I'll redirect you to http://en.wikipedia.org/wiki/Tree_traversal. The concepts are mostly applied to binary trees, but you can extend the idea to arbitrary trees by adding more cases: Effectively, handle a node then recurse, recurse then handle a node, handle all children then recurse into each...etc. There's no canonical categorization of this approach that I'm aware of.

Adam Wright
I know about traversals - so, as I got it right, I need to build 3 types of iterators? in separate classes?
chester89
Yes, you'd probably end up with 3 std::iterator subclasses, one for each traversal type.
Adam Wright
if you're implementing iterators, take a look at boost::iterator_adapter and boost::iterator_facade, separating traversal and element access makes coding iterators a lot easier and cleaner
Pieter
Creating different iterators for different types of traversal is already done in the stl with vector::rbegin() and rend(), so you'd be following standard practice.
Eclipse
@Eclipse: More than that, the STL, according to its designer, was originally intended to support many more iterator types: As in this case, preorder, inorder and postorder iterators for tree structures (such as `std::map`), and row/column iterators for matrices and many others. The only reason the C++ standard library generally only has one type of iterators per container (not counting reverse iterators) is simply time pressure and the added work it'd have meant for the standardization committee. But yes, defining multiple iterator types is fine according to the philosophy behind the STL.
jalf
+2  A: 

If by 'strict' you mean: a single all encompassing definition, you're right, there isn't one.

But 'end' for trees is very well defined, although dependent on the traversal method you're choosing.

  • If you do inorder (or symmetric) traversal, the rightmost element would be end.
  • in preorder (or depth first), the rightmost element would be end, etc.
  • in postorder, the root element would be end, etc.

Most common tree traversal methods.

Pieter
In an inorder traversal, the root is not the end; this is true for a postorder traversal.
Jason
A: 

It depends on what you want to do with the tree - maybe it would be nice to have, for instance, Breadth-First-Search or Depth-First-Search (or both) iterators.

If you have some particular way of scouring the tree, then in effect you do have a beginning and an end. It's not as obvious as the linear relations in lists and sets, but it's there if you want to impose some ordering on it.

Matt
A: 
Roel
+6  A: 

You have to keep something clear when writing an iterator - an iterator for a data structure provides access to a collection as a linear sequence of items. Certain collections, like arrays, lists, and queues, are naturally compatible with being treated as a linear sequence. Other types of collections - trees, dictionaries, graphs - do not necessarily have a simple interpretation as a linear list. In fact, multiple interpretations are generally valid.

What you really to do when writing an iterator for a collection like a tree is address the following concerns:

  1. Where does iteration of the collection begin (root? leaves?)
  2. How does iteration progress to the next element (infix? postfix? suffix? breadth?)
  3. When does iteration terminate (leaves? root? final node?)

Whatever you choose, you should be very clear in how you name (and document) your iterator to make it obvious how it will visit and emit nodes.

You may need to write multiple iterators for the different kinds of traverals you intend to support. There are some good articles here that dicuss tree traversal models.

LBushkin
Bah, I missed this naswer before adding mine.
Pod
+1  A: 

Your definition of an iterator is slightly wrong. Iterators don't go from start to finish, nor front to back. Instead they go across all members of that structure.

If you ask for iteration over an ordered structure, ie an array, linked list etc, you'll (usually) get your members returned in-order.

For unordered items, eg a set, you'll get them in which ever order the set-iterator wants to give you them, but you'll get them all and one-at-a-time, just like you will with an array-iterator.

As for trees, other people have already mentioned: they have a well defined notions of total order, you just have to pick one :)

Pod