簡體   English   中英

鏈表迭代器實現 C++

[英]Linked List Iterator Implementation C++

我在 C++ 中創建了一個鏈接列表,並希望為它實現一個迭代器,以便我可以進行范圍循環: for (const int& i: list) where Linked_List<int> list; .

我的想法是創建Iterator作為Linked_List class 的一部分,如下所示:

這是我到目前為止得到的:

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時進行錯誤檢查嗎? 如果是這樣,我該怎么做? 因為我的 Iterator 沒有帶有尾部的列表 object 。

編輯:我不確定如何實現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;
    }
};

我將如何 go 關於實現Iterator Linked_List<T>::begin() const; 現在end()

我想象一個虛構的用戶制作這樣的迭代器 object: Linked_List<int>::Iterator it;

一個想法是有一個沒有參數的公共構造函數和一個將節點作為參數的私有構造函數, _current將被設置為,並將Linked_List class 作為朋友。

一些筆記。

有兩個選項可以聲明NodeIterator 在列表類內部為List<T>::Node或外部為Node<T> 這在某種程度上是一個品味問題。 但是,從工程的角度來看,嵌套類的符號名稱更長,因此您的調試信息更大。 此外,當嵌套類也是模板時,如果/在必要時更難專門化它們(因為這需要首先完全專門化封閉模板),但這里的情況並非如此。

當一個列表節點用作列表頭和尾時,它會導致更優雅的代碼。 空列表是一個節點,其nextprev指向自己。 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 )。 否則,這些檢查會通過不必要的運行時檢查懲罰正確的應用程序。


這是一個基於您的想法的最小工作示例:

template<class T>
class List;

class Iterator;

class Node {
    friend class Iterator;
    template<class T> friend class List;

protected:
    Node *next_, *prev_;

    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;
    }

public:
    Node()
        : next_(this), prev_(this)
    {}

    ~Node() { unlink(); }
};

class Iterator {
protected:
    Node* node_;

    Iterator(Node* node)
        : node_(node)
    {}

public:
    Iterator& operator++() {
        node_ = node_->next_;
        return *this;
    }

    bool operator==(Iterator b) const { return node_ == b.node_; }
    bool operator!=(Iterator b) const { return node_ != b.node_; }

    // Implement the rest of iterator interface.
};

template<class T>
class List {
    class NodeT : public Node {
        friend class List<T>;
        T value_;
        NodeT(T t) : value_(t) {}
    };

    template<class U>
    class IteratorT : public Iterator {
        friend class List<T>;
        NodeT* node() const { return static_cast<NodeT*>(node_); }
    public:
        U& operator*() const { return node()->value_; }
        U* operator->() const { return &node()->value_; }
        operator IteratorT<U const>() const { return node_; } // iterator to const_iterator conversion
        IteratorT(Node* node) : Iterator{node} {}
    };

    Node list_;

public:
    using iterator = IteratorT<T>;
    using const_iterator = IteratorT<T const>;

    ~List() { clear(); }

    bool empty() const { return list_.next_ == &list_; }

    iterator begin() { return list_.next_; }
    iterator end() { return &list_; }

    void push_back(T t) { list_.push_back(new NodeT(t)); }
    void erase(const_iterator i) { delete i.node(); }

    void clear() {
        while(!empty())
            erase(begin());
    }

    // Implement the rest of the functionality.
};

int main() {
    List<int> l;
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);
    for(auto elem : l)
        std::cout << elem << ' ';
    std::cout << '\n';
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM