简体   繁体   English

重载自定义迭代器的解除引用运算符

[英]Overloading the dereference operator for a custom iterator

This is the first time I've ever played with an iterator so there's probably significant errors. 这是我第一次使用迭代器,因此可能存在重大错误。 I'm attempting to make an inorder iterative iterator class to work in conjunction with my threaded binary search tree. 我正在尝试使有序迭代迭代器类与我的线程二进制搜索树结合使用。 So the iterator is working over nodes. 因此,迭代器正在节点上工作。 I only need the iterator to go through my tree in order so I can print all the values and the frequencies of each node. 我只需要迭代器按顺序遍历我的树,即可打印每个节点的所有值和频率。 However my dereference doesn't seem to be working probably. 但是,我的取消引用似乎不起作用。 This is the method that's giving me trouble: 这是给我带来麻烦的方法:

//-------------------------- inOrderTraverse ------------------------------------
template <typename T>
void ThreadedBST<T>::inOrderTraverse() {
    InorderIterator<T>* iter = new InorderIterator<T>(root);
    ++iter;

    while ((*iter) != NULL)
    {
        cout << (*iter)->getItem() << " " << (*iter)->getFrequency() << endl;
    }
}

Particularly the while loop is throwing compiler errors. 特别是while循环会引发编译器错误。 Here is the exact error: 这是确切的错误:

error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'InorderIterator' 错误C2678:二进制'!=':未找到采用'InorderIterator'类型的左操作数的运算符

I figured the dereference would bring the node out so I'd actually be comparing the node != NULL but that's not what the error message leads me to believe. 我认为取消引用会使该节点退出,因此我实际上是在比较节点!= NULL,但这不是错误消息使我相信的原因。 Here's the full Iterator class: 这是完整的Iterator类:

#ifndef INORDERITER_H
#define INORDERITER_H

#include <iostream>
#include "ThreadedBST.h"
using namespace std;

//---------------------------------------------------------------------------
// InorderIterator<T> class: 
//   -- 
//
// Assumptions:
//   -- <T> implements it's own comparable functionality
//---------------------------------------------------------------------------

template <typename T>
class InorderIterator {

public:
    InorderIterator(node<T> *); //constructor
    InorderIterator<T>& operator++();
    node<T>& operator*();
    const node<T>& operator*() const;

private:
    node<T>* begin;
    node<T>* curr;
    node<T>* prev;
    node<T>* temp;
};

template <typename T>
InorderIterator<T>::InorderIterator(node<T>* root) {
    begin = root;
    temp = NULL;

    while (begin->leftChild != NULL) {
        begin = begin->leftChild;
    }
}

template <typename T>
InorderIterator<T>& InorderIterator<T>::operator++() {
    if (temp == NULL)
        temp = begin;
    else if (rightChildThread) {
        prev = temp;
        temp = temp->rightChild;
    }
    else {
        prev = temp;
        temp = temp->rightChild;

        while (!temp->rightChildThread && (temp->leftChild->getItem() != prev->getItem())) {
            temp = temp->leftChild;
        }
    }

    curr = temp;
    return *this;
}

template <typename T>
node<T>& InorderIterator<T>::operator*() {
    return *curr;
}

template <typename T>
const node<T>& InorderIterator<T>::operator*() const {
    return *curr;
}

#endif

Here's the node class if it's relevant for any reason: 这是由于任何原因而相关的节点类:

#ifndef NODE_H
#define NODE_H

#include <iostream>
using namespace std;

//---------------------------------------------------------------------------
// node<T> class: 
//   -- 
//
// Assumptions:
//   -- <T> implements it's own comparable functionality
//---------------------------------------------------------------------------

template <typename T>
class node {

public:
    node<T>* leftChild;
    node<T>* rightChild;
    bool leftChildThread;
    bool rightChildThread;
    node(T value); //constructor
    node(T value, node<T>*, node<T>*, bool, bool); //secondary constructor
    node(const node<T>&); //copy constructor
    void decrementFrequency(); //decrements by 1 the frequency
    void incrementFrequency(); //increments by 1 the frequency
    int getFrequency(); //returns the frequency
    T getItem(); //returns the item

private:
    T item;
    int frequency;
};

//-------------------------- Constructor ------------------------------------
template <typename T>
node<T>::node(T value) {
    item = value;
    frequency = 1;

}

//-------------------------- Secondary Constructor ------------------------------------
template <typename T>
node<T>::node(T value, node<T>* left, node<T>* right, bool leftThread, bool rightThread) {
    item = value;
    frequency = 1;
    leftChild = left;
    rightChild = right;
    leftChildThread = leftThread;
    rightChildThread = rightThread;
}

//-------------------------- Copy ------------------------------------
template <typename T>
node<T>::node(const node<T>& copyThis) {
    item = copyThis.value;
    frequency = copyThis.frequency;
}

//-------------------------- decrementFrequency ------------------------------------
template <typename T>
void node<T>::decrementFrequency() {
    frequency--;
}

//-------------------------- incrementFrequency ------------------------------------
template <typename T>
void node<T>::incrementFrequency() {
    frequency++;
}

//-------------------------- getFrequency ------------------------------------
template <typename T>
int node<T>::getFrequency() {
    return frequency;
}

//-------------------------- getItem ------------------------------------
template <typename T>
T node<T>::getItem() {
    return item;
}

#endif
  class const_iterator {
    public:
        Node *current;

        const_iterator (Node *n) : current{n}
        {
            /* the body can remain blank, the initialization is carried
             * the the constructor init list above
             */
        }

        /* copy assignment */
        const_iterator operator= (const const_iterator& rhs) {
            this->current = rhs.current;
            return *this;
        }

        bool operator == (const const_iterator& rhs) const {
            return this->current == rhs.current;
        }
        bool operator != (const const_iterator& rhs) const {
            return this->current != rhs.current;
        }

        /* Update the current pointer to advance to the node
         * with the next larger value
         */
        const_iterator& operator++ () {
            /*first step is to go left as far as possible(taken care of by begin())
             once you go as left as possible, go right one step at a time*/
            if(current->right != nullptr){
                current = current->right;
                //every step, go left again as far as possible
                while(current->left != nullptr){
                    current = current->left;
                }
            }else{
                bool upFromLeft = false;
                bool upFromRight = false;
                while(upFromLeft == false && upFromRight == false){
                    //if you have gone all the way up from the right
                    if(current->parent == nullptr){
                        upFromRight = true;
                        current = current->parent;
                        return *this;
                    }
                    //if you have gone all the way back up left
                    if(current->parent->left == current){
                        upFromLeft = true;
                        current = current->parent;
                        return *this;
                    }
                    current = current->parent;
                }
            }
            return *this;
        }

        Z& operator *() const {
            return current->data;
        }
    };

ADD these functions to your tree in order to use the begin() and end() with your iterator 将这些函数添加到树中,以便在迭代器中使用begin()和end()

        const const_iterator begin() const {
        if(rootPtr == nullptr){
            return nullptr;
        }
        Node* temp = rootPtr;
        while(temp->left != nullptr){
            temp = temp->left;
        }
        return const_iterator(temp);
    }

    /* For the "end" marker
     * we will use an iterator initialized to nil */
    const const_iterator end() const {
        return const_iterator(nullptr);
    }

Here's an example of an in-order iterator I wrote in C++... 这是我用C ++编写的有序迭代器的示例...

This iterator assumes that each node in your BST has a pointer to the parent node which is something I don't see in your node class. 该迭代器假定BST中的每个节点都有一个指向父节点的指针,而这在我的节点类中是看不到的。 However, I am not sure its even possible to accomplish an inorder traversal without having a parent pointer. 但是,我不确定在没有父指针的情况下甚至不可能完成有序遍历。

In short, this example will work if you add a parent pointer to your nodes and update your parent pointers every time you do a node insertion or removal 简而言之,如果您向节点添加父指针并在每次插入或删除节点时更新父指针,则此示例将起作用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM