链表迭代器实现C ++

时间:2019-03-28 16:39:32

标签: c++ data-structures iterator

我已经用C ++创建了一个链表,并希望为其实现一个迭代器,以便可以进行范围循环:for (const int& i : list),其中Linked_List<int> list;

我的想法是像这样在Iterator类中创建Linked_List

这是我到目前为止得到的:

template <typename T>
class Linked_List
{
public:
    struct Iterator;
    struct Node;
public:
    Linked_List();
    ~Linked_List() noexcept(false);
    Linked_List(const Linked_List&) = delete;
    Linked_List(Linked_List&&) = delete;
    Linked_List& operator=(const Linked_List&) = delete;
    Linked_List& operator=(Linked_List&&) = delete;

    void push_back(T);
    void push_front(T);
    void pop_back();
    void pop_front();
    bool empty() const;
    T back() const;
    T front() const;
    //void swap(T, T);
    //void insert(Iterator, T);
    //void erase(Iterator);
    //Iterator begin() const;
    //Iterator end() const;
private:
    Node* head;
    Node* tail;
};

template<typename T>
struct Linked_List<T>::Node
{
    Node() : prev(nullptr), next(nullptr) {}
    Node(T t) : value(t), prev(nullptr), next(nullptr) {}
    Node* prev;
    Node* next;
    T value;
};
  1. 这是个好方法吗?
  2. 在递增列表以检查current->next == tail是否应该进行错误检查?如果是这样,我该怎么做?因为我的迭代器没有带尾的列表对象。

修改: 我不确定如何实现struct Iterator;,在弄清楚如何将其与列表连接时会卡住,以便检查迭代器返回的当前节点是否等于列表中的尾部。 Linked_List Iterator end() const方法。

假设我已经为这样的迭代器实现了所有必需的运算符:

struct Iterator
{
    T& operator*() const { return current->value; }
    bool operator!=(const Iterator& rhs) { return (*_current != rhs._current); }
    Iterator& operator++()
    {
        current = current->next;
        return *this;
    }
};

我现在将如何实施Iterator Linked_List<T>::begin() const;end()

我想象一个虚构的用户制作这样的迭代器对象: Linked_List<int>::Iterator it;

一个想法是有一个没有参数的公共构造函数,和一个将节点_current设置为参数,并把Linked_List类作为朋友的私有构造函数。 / p>

1 个答案:

答案 0 :(得分:1)

一些笔记。

有两个用于声明#include <stdio.h> int main(void) { FILE *fp; char s[] = "abcdef"; int i, c; fp = fopen("ot.txt", "w+"); if (fp == NULL) { printf("file open error\n"); return 1; } i = 0; while (s[i] != '\0') { fputc(s[i], fp); i++; printf("%d", i); } rewind(fp); while ((c1 = fgetc(fp)) != EOF) { putchar(c1); } printf("\n"); fclose(fp); return 0; } Node的选项。在列表类内部为Iterator,在外部类为List<T>::Node。部分原因在于口味。但是从工程的角度来看,嵌套类的符号名更长,因此debuginfo更大。另外,如果嵌套类也是模板,则在必要时/很难对其进行专业化处理(因为首先需要完全对封闭模板进行专业化处理),但这不是这种情况。

当一个列表节点用作列表头和尾时,它会导致代码更优美。空列表是其Node<T>next指向其自身的节点。 prev附加到push_front,后者指向第一个节点或本身。 list.next将一个节点附加到push_back,该节点指向最后一个节点或自身。插入/删除节点时,不需要对第一个节点和最后一个节点进行特殊处理。例如。 :

list.prev

在上面,struct Node { Node *next_, *prev_; Node() : next_(this), prev_(this) {} ~Node() { unlink(); } void push_back(Node* n) { n->next_ = this; n->prev_ = prev_; prev_->next_ = n; prev_ = n; } void unlink() { Node *next = next_, *prev = prev_; next->prev_ = prev; prev->next_ = next; next_ = this; prev_ = this; } }; 仅需要两项操作即可维护列表。除此之外,Node本身就是一个极简列表,可用于侵入式列表(在析构函数中具有自动取消链接)。请注意,使用Node是如何使对this的检查变得不必要-nullptr始终是有效列表。

错误检查应仅在调试模式下(例如,使用Node)。否则,这些检查会通过不必要的运行时检查来惩罚正确的应用程序。


这是一个基于您的想法的最小工作示例:

assert