C++AVL树迭代器将无法正确递增



我在AvlTree类中实现了一个类迭代器。我的AvlTree节点如下:

    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 ) { }
};

我的迭代器如下:

     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); }
};

我的AvlTree还有一个作为公共成员的开始和结束迭代器:

    //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 );
}

我的问题是,当我尝试运行以下主要内容时:

    for(AvlTree<string>::iterator itr = tree.begin(); itr != (tree.end()); itr++)
        cout << *itr << endl;

我没有按顺序输出字符串树中的所有单词,而是得到了树中按顺序排列的第一个项目的无限循环。我似乎不明白为什么它不会越过第一个项目。

以下迭代代码有效(来自我的AVL树;用leftright代替link[0]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;
}

就您的代码而言,首先,end()不需要找到最右边的节点来返回iterator(NULL);它可以在不看树的情况下返回。

然而,你的算法中的实际错误似乎在这里:

        temp = t->parent;
WRONG:  while(temp->parent->left != temp)
        {
            temp = temp->parent; //go up 
        }
        //return your parent
WRONG:  temp = t->parent;
        return temp;
    }

我标记的第一行可能会尝试NULL指针取消引用,应该改为:

while(temp->parent && temp->parent->left != temp)

第二个是:

temp = temp->parent;

此外,您可能已经从我的代码中注意到,下面的代码现在非常棒;它可以被删除,并且将由(固定的)剩余代码以完全相同的方式处理。它还受到了我在上面指出的相同的NULL指针取消引用的影响。

//if we are someone's left child, go up one
if(t->parent->left == t)
{
    //return your parent
    temp = t->parent;
    return temp;
}

最新更新