迭代链接列表的迭代器

时间:2014-10-12 02:32:58

标签: c++ linked-list iterator

我正在尝试为我的展开链接列表完成我的迭代器类(链接列表,其中每个节点都有一个项目数组)。除了'=='和'!='重载运算符之外,所有函数都正常工作。我试图让它比较currentNode [currentIndex]的地址,但*和&似乎没有在这些重载运算符上工作。继承我的代码......

class CDAL_Iter : public std::iterator<std::forward_iterator_tag, T>
    {
    public:
        typedef T value_type;
        typedef std::ptrdiff_t difference_type;
        typedef T& reference;
        typedef T* pointer;
        typedef std::forward_iterator_tag iterator_category;
        typedef CDAL_Iter self_type;
        typedef CDAL_Iter& self_reference;

    private:
        Node * currentNode;      //Stores the Node the iterator is currently on
        int currentIndex;
        //T * currentPointer = &currentNode[currentIndex];

    public:
        explicit CDAL_Iter( Node* start, int index) : currentNode( start ), currentIndex( index ) {}   //Constructor which sets current node to beginning of list

        CDAL_Iter( const CDAL_Iter& src ) : currentNode( src.currentNode ), currentIndex( src.currentIndex) {}      //copy constructor

        reference operator*() const {   //overloaded operator for access to current iterators contents
            return currentNode->array[currentIndex];
        }

        pointer operator->() const {                            //overloaded operator for access to member functions
            return &this;
        }

        self_reference operator=( const CDAL_Iter& src ) {     //overloaded operator for copy assignment

            this->currentNode = src.currentNode;
            this->currentIndex = src.currentIndex;
            return *this;
        }

        self_reference operator++() {                           // preincrements iterator
            ++currentIndex;

            if(currentIndex % 50 == 0) {
                currentNode = currentNode->next;
                currentIndex = 0;
            }

            return *this;
        }
        self_type operator++(int) {                             // postincrements iterator
            self_type temp (*this);
            ++(*this);
            return temp;
        }

        bool operator==(const CDAL_Iter& rhs) const {               //checks two iterators for equality
            return (this->currentNode[currentIndex] == rhs.currentNode[currentIndex]);
        }

        bool operator!=(const CDAL_Iter& rhs) const {               //checks two iterators for inequality
            return ( &this->currentNode[currentIndex] != &rhs.currentNode[currentIndex] );
        }
    }; // end CDAL_Iter

    typedef std::size_t size_type;
    typedef T value_type;
    typedef CDAL_Iter iterator;

    iterator begin() { return CDAL_Iter( head, 0 ); }  //returns iterator to beginning of list
    iterator end() { return CDAL_Iter(lastNode(), size() % 50 ); }  //returns iterator (pointer) to end of list                          

我已经想出了下面代码的解决方法,但它并没有比较地址,按照我的意愿。当我复制迭代器并尝试遍历复制的迭代器内容时,这也会崩溃....

bool operator==(const CDAL_Iter& rhs) const {               //checks two iterators for equality
            if(this->currentNode == rhs.currentNode && this->currentIndex == rhs.currentIndex) {
                return true;
            }

            else {
                return false;
            }
        }

        bool operator!=(const CDAL_Iter& rhs) const {               //checks two iterators for inequality
            if(this->currentNode == rhs.currentNode && this->currentIndex == rhs.currentIndex) {
                return false;
            }

            else {
                return true;
            }
        }

1 个答案:

答案 0 :(得分:0)

@ Igor这是我班上其他人的代码。当我试图遍历它时,我难以理解为什么我复制的迭代器会因访问代码异常而崩溃。

#ifndef _CDAL_H_
#define _CDAL_H_

#include <iostream>
#include <stdexcept>
#include <cstddef>

namespace COP3530 {

template <class T>
class CDAL {

private:

    struct Node {

        int array_size = 0;     //Array 's current number of items
        T *array;             //Pointer to Node's array

        Node *next = NULL;      //Defines the pointer that this node is pointing to

        Node()  {                //Node constructor
            array = new T[50];  //Dynamically allocates a new array of size 50
        }
        ~Node() {              //Array destructor
            delete[] array;
        }

    };
//---------------------------------------------------------------------------------------------------------------------------------------------------------

    size_t nodeCount() const {

        if(head == NULL) {
            return 0;
        }

        else {
            int nodeCount = 0;

            Node * currentNode = head;

            while(currentNode != NULL) {
                ++nodeCount;
                currentNode = currentNode->next;
            }
            return nodeCount;
        }

    }

    Node * lastNode() const {
        Node * currentNode = head;        //Set Current node as head to traverse

        int nodeNum = size() / 50;     //finds last node number to go to

        if(size() % 50 == 0) {         //makes it so it doesnt go past node number
            --nodeNum;
        }

        for(int i = 0; i < nodeNum; ++i) {      //Traverses to node number with last element
            currentNode = currentNode->next;
        }

        return currentNode;
    }

    void cleanup() {
        int usedNodes = size() / 50;
        int un_usedNodes = nodeCount() - usedNodes;

        if(un_usedNodes > usedNodes) {


            int finalUsedNode = un_usedNodes / 2;
            int nodeNum = size() / 50;
            if(size() % 50 == 0) {
                --nodeNum;
            }

            nodeNum += finalUsedNode;

            Node * currentNode = head;

            for(int i = 0; i < nodeNum; ++i) {
                currentNode = currentNode->next;
            }

            tail = currentNode;

            currentNode = currentNode->next;;
            Node * next = NULL;

            while(currentNode != NULL) {

                next = currentNode->next;
                delete currentNode;
                currentNode = NULL;
                currentNode = next;
            }

            tail->next = NULL;

        }

    }

    Node *head = NULL;      //Head node
    Node *tail = NULL;      //Tail node

//---------------------------------------------------------------------------------------------------------------------------------------------------------

public:

    class CDAL_Iter : public std::iterator<std::forward_iterator_tag, T>
    {
    public:
        typedef T value_type;
        typedef std::ptrdiff_t difference_type;
        typedef T& reference;
        typedef T* pointer;
        typedef std::forward_iterator_tag iterator_category;
        typedef CDAL_Iter self_type;
        typedef CDAL_Iter& self_reference;

    private:
        Node * currentNode;      //Stores the Node the iterator is currently on
        int currentIndex;

    public:
        explicit CDAL_Iter( Node* start, int index) : currentNode( start ), currentIndex( index ) {}   //Constructor which sets current node to beginning of list

        CDAL_Iter( const CDAL_Iter& src ) : currentNode( src.currentNode ), currentIndex( src.currentIndex) {}      //copy constructor

        reference operator*() const {   //overloaded operator for access to current iterators contents
            return currentNode->array[currentIndex];
        }

        pointer operator->() const {                           
            return &(currentNode->array[currentIndex]);
        }

        self_reference operator=( const CDAL_Iter& src ) {     //overloaded operator for copy assignment

            this->currentNode = src.currentNode;
            this->currentIndex = src.currentIndex;
            return *this;
        }

        self_reference operator++() {                           // preincrements iterator
            ++currentIndex;

            if(currentIndex % 50 == 0) {
                currentNode = currentNode->next;
                currentIndex = 0;
            }

            return *this;
        }
        self_type operator++(int) {                             // postincrements iterator
            self_type temp (*this);
            ++(*this);
            return temp;
        }

        bool operator==(const CDAL_Iter& rhs) const {               //checks two iterators for equality
            if(this->currentNode == rhs.currentNode && this->currentIndex == rhs.currentIndex) {
                return true;
            }

            else {
                return false;
            }
        }

        bool operator!=(const CDAL_Iter& rhs) const {               //checks two iterators for inequality
            if(this->currentNode == rhs.currentNode && this->currentIndex == rhs.currentIndex) {
                return false;
            }

            else {
                return true;
            }
        }
    }; // end CDAL_Iter

    class Const_CDAL_Iter : public std::iterator<std::forward_iterator_tag, T>
    {
    public:
        typedef T value_type;
        typedef std::ptrdiff_t difference_type;
        typedef T& reference;
        typedef T* pointer;
        typedef std::forward_iterator_tag iterator_category;
        typedef Const_CDAL_Iter self_type;
        typedef Const_CDAL_Iter& self_reference;

    private:
        Node * currentNode;      //Stores the Node the iterator is currently on
        int currentIndex;

    public:
        explicit Const_CDAL_Iter( Node* start, int index) : currentNode( start ), currentIndex( index ) {}   //Constructor which sets current node to beginning of list

        Const_CDAL_Iter( const Const_CDAL_Iter& src ) : currentNode( src.currentNode ), currentIndex( src.currentIndex) {}      //copy constructor

        reference operator*() const {   //overloaded operator for access to current iterators contents
            return currentNode->array[currentIndex];
        }

        pointer operator->() const {
            return &(currentNode->array[currentIndex]);
        }

        self_reference operator=( const CDAL_Iter& src ) {     //overloaded operator for copy assignment

            this->currentNode = src.currentNode;
            this->currentIndex = src.currentIndex;
            return *this;
        }

        self_reference operator++() {                           // preincrements iterator
            ++currentIndex;

            if(currentIndex % 50 == 0) {
                currentNode = currentNode->next;
                currentIndex = 0;
            }

            return *this;
        }
        self_type operator++(int) {                             // postincrements iterator
            self_type temp (*this);
            ++(*this);
            return temp;
        }

        bool operator==(const Const_CDAL_Iter& rhs) const {               //checks two iterators for equality
            if(this->currentNode == rhs.currentNode && this->currentIndex == rhs.currentIndex) {
                return true;
            }

            else {
                return false;
            }
        }

        bool operator!=(const Const_CDAL_Iter& rhs) const {               //checks two iterators for inequality
            if(this->currentNode == rhs.currentNode && this->currentIndex == rhs.currentIndex) {
                return false;
            }

            else {
                return true;
            }
        }
    }; // end Const_CDAL_Iter


    typedef std::size_t size_type;
    typedef T value_type;
    typedef CDAL_Iter iterator;
    typedef Const_CDAL_Iter const_iterator;

    iterator begin() { return CDAL_Iter( head, 0 ); }                      //returns iterator to beginning of list
    iterator end() { return CDAL_Iter( lastNode(), size() % 50 ); }                              //returns iterator (pointer) to end of list
    const_iterator begin() const { return Const_CDAL_Iter( head, 0 ); }     //returns const iterator (pointer) to beginning of list
    const_iterator end() const { return Const_CDAL_Iter( lastNode(), size() % 50 ); }             //returns const iterator (pointer) to end of list

    CDAL() {}

    CDAL(const CDAL& src ) {

        for(int i = 0; i < src.size(); ++i) {    // populate this CDAL with copies of the other CDAL's contents
            this->push_back(src.item_at(i));
        }
    }

    ~CDAL() {
        if(!is_empty()) {
            clear();
        }
    }

    CDAL& operator=(const CDAL& rhs) {
        if ( &rhs == this ) // check for self-assignment
            return *this;     // do nothing

        this->~CDAL();      // safely dispose of this CDAL's contents

        for(int i = 0; i < rhs.size(); ++i) {    // populate this CDAL with copies of the other CDAL's contents
            this->push_back(rhs.item_at(i));
        }
        return *this;
    }

    T replace(const T& element, int position) {
        if(position>= size() || position < 0 || is_empty()) {     //If invalid position, throws exception
            throw std::domain_error("not a valid position!");
        }

        else {
            int nodeNum = position / 50;     //Position of node to insert at
            int index = position % 50;       //Position of index in node to insert at

            Node * currentNode = head;

            for(int i = 0; i < nodeNum; ++i) {     //Traverse the node until desired node is reached
                currentNode = currentNode->next;
            }

            T temp = currentNode->array[index];
            currentNode->array[index] = element;
            return temp;
        }
    }

    void insert(const T& element, int position) {
        if(position> size() || position < 0) {     //If invalid position, throws exception
            throw std::domain_error("not a valid position!");
        }

        else if(position == size()) {       //If position equals size, append to end of list
            push_back(element);
        }

        else {

            int nodeNum = position / 50;     //Position of node to remove from
            int index = position % 50;       //Position of index in remove at

            Node * currentNode = head;

            for(int i = 0; i < nodeNum; ++i) {    //Navigates to node to insert to
                currentNode = currentNode->next;
            }

            if(currentNode->array_size < 50) {                               //If there's space on the array to shift, do so
                for(int i = currentNode->array_size-1; i >= index; --i) {
                    std::swap(currentNode->array[i+1], currentNode->array[i]);     //Shift elements up the list
                }

                currentNode->array[index] = element;    //Inserts new element into desired position
                ++currentNode->array_size;    //Increase size of list
            }

            else {                                      //If there is not space in current node to shift, spill over into next nodes

                T last = currentNode->array[49];    //Save last element of array as temp to spill over to next node
                for(int i = currentNode->array_size-1; i >= index; --i) {
                    std::swap(currentNode->array[i+1], currentNode->array[i]);      //Shift elements up the list
                }
                currentNode->array[index] = element;       //Inserts new element into desired position

                int finishNode = (size()/50) - nodeNum;      //Finds all elements to right of deleted position, and shifts to left
                if(size() % 50 == 0) {
                    --finishNode;
                }

                for(int c = 0; c < finishNode; ++c) {

                    currentNode = currentNode->next;

                    T newLast = currentNode->array[49];
                    for(int i = currentNode->array_size-1; i >= 0; --i) {
                        std::swap(currentNode->array[i+1], currentNode->array[i]);      //Shift elements up the list
                    }
                    currentNode->array[0] = last;
                    last = newLast;

                }

                if(currentNode->array_size != 50 ) {
                    ++currentNode->array_size;
                }

                else {
                    if(currentNode->next == NULL) {
                        tail->next = new Node();
                        tail = tail->next;
                        tail->array[0] = last;
                        ++tail->array_size;
                    }

                    else {
                        currentNode = currentNode->next;
                        currentNode->array[0] = last;
                        ++currentNode->array_size;
                    }
                }
            }

        }
    }

    void push_front(const T& element) {
        if(head == NULL) {
            head = new Node();
            tail = head;
            head->array[head->array_size] = element;
            ++head->array_size;
        }

        else {
            insert(element, 0);
        }
    }

    void push_back(const T& element) {      //Appends element to last position
        if(head == NULL) {
            head = new Node();          //If head is NULL, sets head to a new node with array sized 50
            tail = head;
            head->array[0] = element;
            ++head->array_size;         //Increases Head nodes array size
        }

        else if(size() == 0 && nodeCount() != 0) {
            head->array[0] = element;
            ++head->array_size;
        }

        else if(size() % 50 == 0) {      //If at end of current nodes array and no space for more, add new node to tail

            int nodeNum = size() / 50;
            --nodeNum;

            Node * currentNode = head;

            for(int i = 0; i < nodeNum; ++i) {     //Traverse the node until desired node is reached
                currentNode = currentNode->next;
            }

            if(currentNode->next != NULL) {
                currentNode->next->array[0] = element;
                ++currentNode->next->array_size;
            }

            else {
                currentNode->next = new Node();
                tail = currentNode->next;
                tail->array[0] = element;
                ++tail->array_size;
            }



        }

        else  {

            int nodeNum = size() / 50;     //Position of node to append to

            Node * currentNode = head;

            for(int i = 0; i < nodeNum; ++i) {     //Traverse the node until desired node is reached
                currentNode = currentNode->next;
            }

            currentNode->array[currentNode->array_size] = element;     //Adds element
            ++currentNode->array_size;

        }

    }

    T pop_front() {
        T temp = remove(0);
        cleanup();
        return temp;
    }

    T pop_back() {

        if(is_empty()) {
            throw std::out_of_range("List is empty, cannot remove from back");         //If list empty, cannot remove any elements
        }

        else {
            Node * currentNode = head;        //Set Current node as head to traverse

            int nodeNum = size() / 50;     //finds last node number to go to

            if(size() % 50 == 0) {         //makes it so it doesnt go past node number
                --nodeNum;
            }

            for(int i = 0; i < nodeNum; ++i) {      //Traverses to node number with last element
                currentNode = currentNode->next;
            }

            T temp = currentNode->array[currentNode->array_size];
            --currentNode->array_size;
            cleanup();
            return temp;
        }
    }

    T remove (int position) {
        if(position>= size() || position < 0) {     //If invalid position, throws exception
            throw std::domain_error("not a valid position!");
        }

        else if(is_empty()) {
            throw std::out_of_range("list already empty!");
        }

        else if(position == size() - 1) {
            T temp = pop_back();
            cleanup();
            return temp;

        }

        else {

            int nodeNum = position / 50;     //Position of node to remove from
            int index = position % 50;       //Position of index in remove at

            Node * currentNode = head;

            for(int i = 0; i < nodeNum; ++i) {    //Navigates to node to remove from
                currentNode = currentNode->next;
            }

            T temp = currentNode->array[index];    //Stores element to be delete into a temporary variable

            for(int i = index; i < currentNode->array_size-1; ++i) {          //Shifts elements in array in node to the left
                std::swap(currentNode->array[i+1], currentNode->array[i]);
            }

            if(currentNode->next == NULL ||  currentNode->next->array_size == 0) {
                --currentNode->array_size;
            }

            else {

                int finishNode = (size() - 1 - position) / 50;      //Finds all elements to right of deleted position, and shifts to left

                for(int c = 0; c < finishNode-1; ++c) {
                    currentNode->array[49] = currentNode->next->array[0];

                    currentNode = currentNode->next;

                    for(int i = 0; i < currentNode->array_size-1; ++i) {          //Shifts elements in array to the left
                        std::swap(currentNode->array[i+1], currentNode->array[i]);
                    }
                }

                currentNode->array[49] = currentNode->next->array[0];
                for(int i = 0; i < currentNode->next->array_size; ++i) {
                    std::swap(currentNode->next->array[i+1], currentNode->next->array[i]);
                }
                --currentNode->next->array_size;

            }

            cleanup();
            return temp;

        }

    }

    T item_at(int position) const {
        if(position>= size() || position < 0 || is_empty()) {     //If invalid position, throws exception
            throw std::domain_error("not a valid position!");
        }

        else {
            int nodeNum = position / 50;     //Position of node to insert at
            int index = position % 50;       //Position of index in node to insert at

            Node * currentNode = head;

            for(int i = 0; i < nodeNum; ++i) {     //Traverse the node until desired node is reached
                currentNode = currentNode->next;
            }

            T temp = currentNode->array[index];
            return temp;
        }

    }

    bool is_empty() const {    //Returns true if list is empty, else false
        return (size() == 0);
    }

    size_type size() const {    //Returns number of items in list

        if(head == NULL) {
            return 0;
        }

        else {
            int count = 0;
            Node * currentNode = head;

            while(currentNode != NULL) {
                for(int j = 0; j < currentNode->array_size; ++j) {
                    ++count;
                }
                currentNode =currentNode->next;
            }

            return count;
        }
    }

    void clear() {

        if(head == NULL) {
            return;
        }

        Node * currentNode = head;
        Node * next = NULL;

        while(currentNode != NULL) {

            next = currentNode->next;
            delete currentNode;
            currentNode = NULL;
            currentNode = next;
        }

        head = NULL;
        tail = NULL;
    }

    bool contains(const T& element, bool (*fpr)(const T& a,const T& b)) const   {

        bool ans = false;

        Node * currentNode = head;

        while(currentNode != NULL) {
            for(int j = 0; j < currentNode->array_size; ++j) {

                ans = fpr(element, currentNode->array[j]);
                if(ans) {
                    return true;
                }

            }
            currentNode =currentNode->next;
        }

        return false;

    }

    std::ostream& print(std::ostream& out) {    //Prints out all items in list
        if(is_empty()) {
            out << "<empty list>";
        }

        else if(size() == 1) {
            out << "<[" << head->array[0] << "]>";
        }

        else {

            Node * currentNode = head;

            out << "<" << "[" << currentNode->array[0];

            int set = 0;

            if(size() >= 1) {

                while(currentNode != NULL) {
                    for(int j = 0; j < currentNode->array_size; ++j) {
                        if(set == 0) {
                            j = 1;
                            ++ set;
                        }
                        out << "," << currentNode->array[j];

                    }
                    currentNode =currentNode->next;
                }

            }

            out << "]>";
        }
        return out;
    }
};
}

#endif