Reputation: 53
I have implemented a class iterator inside my AvlTree class. My AvlTree node is as follows:
struct AvlNode
{
Comparable element;
list<int> lines; //line occurrences
bool flag; //checks validity
AvlNode *left;
AvlNode *right;
AvlNode *parent; //parent pointer
int height;
AvlNode( const Comparable & theElement, AvlNode *lt, AvlNode *rt, AvlNode *pt,
int h = 0, bool b = true )
: element( theElement ), left( lt ), right( rt ), parent( pt ), height( h ), flag( b ) { }
};
My iterator is as follows:
class iterator
{
protected:
friend class AvlTree<Comparable>;
AvlNode * node;
AvlNode * findInOrderSuccessor(AvlNode * & t)
{
AvlNode * temp;
//node has a right child
// so successor is leftmost node of right subtree
if(t->right != NULL)
{
temp = t->right; //go right
//go all the way left
while(temp->left != NULL)
{
temp = temp->left;
}
return temp;
}
//node has no right child
//if we are someone's left child, go up one
if(t->parent->left == t)
{
//return your parent
temp = t->parent;
return temp;
}
//if we are someone's right child, go up until the current node
//is someone's left child, then go up one more
temp = t->parent;
while(temp->parent->left != temp)
{
temp = temp->parent; //go up
}
//return your parent
temp = t->parent;
return temp;
}
public:
iterator(AvlNode * p) : node(p)
{ }
//overload * to make *iterator return the element of its node
Comparable & operator*()
{ return node->element; }
iterator operator++ (int) //postfix operator
{
node = findInOrderSuccessor(node);
return iterator(node);
}
// == comparison overload
bool operator==(iterator rhs)
{ return node == rhs.node; }
// != comparison overload
bool operator!=(iterator rhs)
{ return !(*this == rhs); }
};
My AvlTree also has a begin and end iterator as public members:
//begin iterator points to leftmost node
iterator begin()
{ //return pointer to leftmost node
AvlNode *temp = root;
while(temp->left != NULL)
temp = temp->left;
return iterator(temp);
}
//end iterator points to one after rightmost node
iterator end()
{ //return NULL right pointer of rightmost node
AvlNode * temp = root;
while(temp->right != NULL)
temp = temp->right;
return iterator( temp->right );
}
My problem is that when I try to run the following in main:
for(AvlTree<string>::iterator itr = tree.begin(); itr != (tree.end()); itr++)
cout << *itr << endl;
Instead of outputting all the words in the string tree inorder, I get an infinite loop of the first in order item in the tree. I can't seem to figure out why it would not be moving past the first item.
Upvotes: 2
Views: 1960
Reputation: 8095
The following iteration code works (from my AVL tree; substitute left
and right
for link[0]
and link[1]
):
BAVLNode * BAVL_GetFirst (const BAVL *o)
{
if (!o->root) {
return NULL;
}
BAVLNode *n = o->root;
while (n->link[0]) {
n = n->link[0];
}
return n;
}
BAVLNode * BAVL_GetNext (const BAVL *o, BAVLNode *n)
{
if (n->link[1]) {
n = n->link[1];
while (n->link[0]) {
n = n->link[0];
}
} else {
while (n->parent && n == n->parent->link[1]) {
n = n->parent;
}
n = n->parent;
}
return n;
}
As far as your code is concerned, first, end()
does not need to find the rightmost node in order to return iterator(NULL)
; it could just return that without looking at the tree.
The actual error in your algorithm however seems to be here:
temp = t->parent;
WRONG: while(temp->parent->left != temp)
{
temp = temp->parent; //go up
}
//return your parent
WRONG: temp = t->parent;
return temp;
}
The first line I flagged may attempt a NULL pointer dereference, and should be changed to:
while(temp->parent && temp->parent->left != temp)
And the second one to:
temp = temp->parent;
Also, you might have noticed from my code that the following is now superfulous; it can be removed, and will be handled exactly the same way by the (fixed) remaining code. It also suffers from the same NULL pointer dereference I pointed out just above.
//if we are someone's left child, go up one
if(t->parent->left == t)
{
//return your parent
temp = t->parent;
return temp;
}
Upvotes: 1