سؤال

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. Here is the exact error:

error C2678: binary '!=' : no operator found which takes a left-hand operand of type '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. Here's the full Iterator class:

#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

        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++...

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. 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 مع الإسناد
لا تنتمي إلى StackOverflow
scroll top