【问题标题】:Problems with Doubly-Linked List iterator implementation双链表迭代器实现的问题
【发布时间】:2013-11-20 16:32:06
【问题描述】:

我在使用简单的双向链表类时遇到了一些问题。

这是我所有的代码:

/*
 * DLList.h
 *
 *  Created on: Nov 19, 2013
 *      Author: tyler
 */

#ifndef DLLIST_H_
#define DLLIST_H_
#include <iostream>
using namespace std;

template <typename T>
class DLList{
private:
struct DLLNode{
private:
    T data_;
    bool visited_;
    DLLNode* next_;
    DLLNode* prev_;
public:

    DLLNode(T data){
        this->data_ = data;
        visited_ = false;
        next_ = NULL;
        prev_ = NULL;
    }

    void setData(T data){
        this->data_ = data;
    }

    void visit(){
        visited_ = true;
    }

    void unvisit(){
        visited_ = false;
    }

    void setNext(DLLNode* next){
        this->next_ = next;
    }

    void setPrev(DLLNode* prev){
        this->prev_ = prev;
    }

    T& getData(){
        return data_;
    }

    bool getVisited(){
        return visited_;
    }

    DLLNode* getNext(){
        return next_;
    }

    DLLNode* getPrev(){
        return prev_;
    }
};

    DLLNode* head_;
    DLLNode* tail_;

public:
    DLList(){
        head_ = NULL;
        tail_ = NULL;
    }

    class DLLiterator{
    private:
        DLLNode* node;
    public:
        DLLiterator(){
            node = head_;
        }
        T& operator*(const DLLiterator& iter){
            return iter.node->getData();
        }
        DLLiterator& operator++(const DLLiterator& iter){
            if(node->getNext() != NULL)
                node = node->getNext;
            else
                node = NULL;
            return *this;
        }
    };   

    bool isEmpty(){
        return (head_ == NULL);
    }

    void addNodeEnd(T data){
        DLLNode* temp = new DLLNode(data);

        if(isEmpty()){
            head_ = temp;
            tail_ = temp;
        }
        else{
            DLLNode* curr;
            curr = tail_;
            curr->setNext(temp);
            temp->setPrev(curr);
            tail_ = temp;
        }
    } 

    bool contains(T data){
        for(DLLNode* start = head_; start != NULL; start = start->getNext()){
            if(start->getData() == data)
                return true;
        }
        return false;
    }

    void remove(T data){
        for(DLLNode* curr = head_; curr != NULL; curr = curr->getNext()){
            DLLNode* key = curr;
            if(curr->getData() == data){
                if(curr == head_){
                    head_ = key->getNext();
                    key->getNext()->setPrev(NULL);
                    delete key;
                }
                if(curr == tail_){
                    tail_ = key->getPrev();
                    key->getPrev()->setNext(NULL);
                    delete key;
                }
                else{
                    DLLNode* prev;
                DLLNode* next;
                    prev = key->getPrev();
                    next = key->getNext();
                    prev->setNext(next);
                    next->setPrev(prev);
                    delete key;
                }
            }
        }
    }

    void printList(){
        for(DLLNode* curr = head_; curr != NULL; curr = curr->getNext()){
            cout << curr->getData() << "\n";
        }
    }
};



#endif /* DLLIST_H_ */

我的问题是我不知道如何在外部类中实际使用迭代器。其他一切都经过测试,似乎工作正常。仍然需要添加一个简单的析构函数,但我现在的重点是迭代器。任何帮助都会很棒。

我试着做:

DLLiterator iter;

但这显然是错误的......

编辑:这是 operator++ 代码:

iterator operator++(){
    if(node_->getNext() != NULL)
        node_ = node_->getNext;
    else
        node_ = NULL;
    return *this;
}

但现在它要求int 作为参数...?

【问题讨论】:

  • 相当多的代码,缩进略有损坏,但如果你问如何声明链表的迭代器:像这样:DLList&lt;int&gt;::iterator iter;
  • 不会是DLList&lt;int&gt;::DLLiterator iter吗?
  • IMO 您应该将 * 和 ++ 运算符重载函数更改为“不接受”任何输入参数。

标签: c++ list iterator


【解决方案1】:

在课堂之外,您必须使用限定名称DLList&lt;whatever&gt;::DLLiterator。您可以看到将疣添加到嵌套名称中没有什么意义,除非您希望您的名称难以阅读:它只是部分重复了范围名称。我会把它重命名为iterator

现在您的问题是它尝试使用列表的成员 head_ 初始化自己,但它无权访问列表以从中提取头部。您可能希望遵循标准容器的示例,并通过列表的成员创建一个迭代器:

iterator begin() {return iterator(head_);}

并相应地修改迭代器的构造函数。

在 C++11 中,这意味着用户通常根本不需要写出讨厌的限定名;你可以得到一个迭代器

auto it = list.begin();

最后,从迭代器的operator*operator++ 中删除参数。由于它们是成员函数,因此它们的操作数作为 this 隐式传递,而不是作为参数显式传递。

【讨论】:

  • 这确实有帮助,但现在 operator++ 要求 int 作为参数...查看编辑。
  • @tbgeorge:你只实现了预增量,++it。如果您还需要后增量,it++,那么您也需要operator++(int)。 (虚拟参数表示它是后增量,但没有任何其他含义)。这将需要在递增之前复制迭代器,并按值返回该副本。
  • 好的,我解决了这个问题,但现在我得到了这个:error: cannot convert ‘DLList&lt;T&gt;::DLLNode::getNext&lt;std::basic_string&lt;char&gt; &gt;’ from type ‘DLList&lt;std::basic_string&lt;char&gt; &gt;::DLLNode* (DLList&lt;std::basic_string&lt;char&gt; &gt;::DLLNode::)()’ to type ‘DLList&lt;std::basic_string&lt;char&gt; &gt;::DLLNode*’ 从这一行node_ = node_-&gt;getNext;
  • @tbgeorge:查看编译器指向的行,找出问题所在。 (提示:要调用函数,请使用())。
  • 哇,我很笨,完全看过了。谢谢。
猜你喜欢
  • 2016-09-27
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 1970-01-01
  • 2012-01-22
  • 2013-02-22
  • 1970-01-01
相关资源
最近更新 更多