简体   繁体   English

c ++如何为双向链表实现迭代器

[英]c++ how implement iterator for a doubly linked list

I am using this text book 我正在使用这本教科书

http://cpp.datastructures.net http://cpp.datastructures.net

chapter 5 iterator usage: 第5章迭代器用法:

http://cpp.datastructures.net/source/ch05/CPP/IteratorPrint.cpp-DSACiterator.html http://cpp.datastructures.net/source/ch05/CPP/IteratorPrint.cpp-DSACiterator.html

here is how i implement it (the ObjectIterator class) 这是我如何实现它(ObjectIterator类)

#include <iostream>

using namespace std;

class PositionException {
protected:
    string message;
public:
    PositionException(const string &m) {
        message = m;
    }
    void print() {
        cout << message << endl;
    }
};


template <typename T>

class NodeList {

protected:

    struct Node {
        Node *prev;
        Node *next;
        T item;
        Node(T i = T(), Node *p = NULL, Node *n = NULL) : item(i), prev(p), next(n) {}

    };


    typedef Node * NodePtr;

public:
    class Position {
    protected:
        NodePtr node;
    public:
        bool isNull() {
            return node == NULL;
        }
        Position(NodePtr n = NULL) : node(n) {}
        T& element() {
            return node->item;
        }

        friend class NodeList;
    };


    class ObjectIterator {
    protected:
        NodePtr node;
    public:
        ObjectIterator(NodePtr n = NULL) : node(n) {}

        bool hasNext() {

            if (node->next == NULL) {
                return false;
            }

            if (node->next->next == NULL) {
                return false;
            }
            return true;
        }
        ObjectIterator next() {
            return ObjectIterator(node->next);
        }
        T& element() {
            return node->item;
        }
        friend class NodeList;


    };

protected:
    int sz;
    NodePtr header;
    NodePtr trailer;

public:
    NodeList() {
        header = new Node();
        trailer = new Node();
        header->next = trailer;
        trailer->prev = header;
        sz = 0;
    }

    bool isEmpty() const {
        return size() == 0;
    }
    int size() const {
        return sz;
    }

    bool isFirst(const Position& p) const {
        return p.node->prev == header;
    }
    bool isLast(const Position& p) const {
        return p.node->next = trailer;
    }


    Position first() const {
        if (isEmpty()) {
            throw PositionException("no first for empty list");
        }
        return Position(header->next);
    }

    Position last() const {
        if (isEmpty()) {
            throw PositionException("no last for emtpy list");
        }
        return Position(trailer->prev);
    }


    Position before(const Position& p) const{
        if (p.node->prev == header) {
            throw PositionException("already the first element, nothing before it");
        }
        return Position(p.node->prev);
    }

    Position after(const Position& p) const{
        if (p.node->next == trailer) {
            throw PositionException("already the last element, nothing after it");
        }
        return Position(p.node->next);
    }




    Position insertAfter(const Position& p, const T& o) {
        NodePtr node = new Node(o, p.node, p.node->next);
        p.node->next->prev = node;
        p.node->next = node;
        sz++;
        return Position(node);
    }

    Position insertBefore(const Position& p, const T& o) {
        NodePtr node = new Node(o, p.node->prev, p.node);
        p.node->prev->next = node;
        p.node->prev = node;
        sz++;
        return Position(node);
    }

    void remove(const Position& p) {
        p.node->prev->next = p.node->next;
        p.node->next->prev = p.node->prev;

        sz--;
        delete p.node;
    }

    void removeFirst() {
        remove(first());
    }

    void removeLast() {
        remove(last());
    }


    void replaceElement(const Position& p, const T& element) {
        if (p.isNull()) {
            throw PositionException("p is null");
        }
        p.node->item = element;
    }

    Position insertFirst(const T& o) {
        NodePtr node = new Node(o, header, header->next);
        header->next->prev = node;
        header->next = node;
        sz++;
        return Position(node);
    }

    Position insertLast(const T& o) {
        NodePtr node = new Node(o, trailer->prev, trailer);
        trailer->prev->next = node;
        trailer->prev = node;
        sz++;
        return Position(node);
    }

    void copyFrom(const NodeList<T>& nl) {
        sz = nl.sz;

        if (nl.sz > 0) {
            Position p0 = nl.first();
            Position p = insertFirst(p0.node->item);

            while (!nl.isLast(p0)) {
                p0 = nl.after(p0);
                insertAfter(p, p0.node->item);
            }
        }
    }

    void emptyList() {
        while (!isEmpty()) {
            removeFirst();
        }
    }

    ~NodeList() {
        emptyList();
        delete header;
        delete trailer;
    }

    NodeList<T>& operator=(const NodeList<T>& nl) {
        emptyList();
        copyFrom(nl);
    }

    NodeList(const NodeList<T>& nl) {
        emptyList();
        copyFrom(nl);
    }

    void print() {
        cout << "size is: " << size() << endl;

        if (size() > 0) {
            ObjectIterator i = elements();
            while (i.hasNext()) {
                cout << i.element() << "\t";
                i = i.next();
            }
            cout << endl;
        }
    }


    ObjectIterator elements() {
        if (isEmpty()) {
            throw PositionException("iterator error: empty");
        }
        return ObjectIterator(header->next);
    }

    void swapItems(const Position& p1, const Position& p2) {
        T temp = p1.node->item;
        p1.node->item = p2.node->item;
        p2.node->item = temp;

    }

};

If i don't use the iterator, the following code for printing is correct 如果我不使用迭代器,下面的打印代码是正确的

void print() {
    if (size() > 0) {

        NodePtr n = header->next;
        while (n != trailer) {
            cout << n->item << "\t";
            n = n->next;
        }

        cout << endl;
    }

}

If I use the iterator for the print function 如果我使用迭代器作为打印功能

void print() {
    cout << "size is: " << size() << endl;

    if (size() > 0) {
        ObjectIterator i = elements();
        while (i.hasNext()) {
            cout << i.element() << "\t";
            i = i.next();
        }
        cout << endl;
    }
}

one of the node is missing. 其中一个节点丢失了。 The book does not provide the correct way to implement the iterator 本书没有提供实现迭代器的正确方法

your hasNext() function is correct for a doubly linked list, providing that trailer's next is NULL. 你的hasNext()函数对于双向链表是正确的,假设预告片的下一个是NULL。 the error is the usage in the print function 错误是打印功能中的用法

void print() {
    cout << "size is: " << size() << endl;

    if (size() > 0) {
        ObjectIterator i = elements();

        while (true) {
            cout << i.element() << "\t";
            if (i.hasNext())
                i = i.next();
            else
                break;

        }
        cout << endl;
    }
}

EDIT: the above code only do debugging for you. 编辑:上面的代码只为你做调试。 it's not how you implement the 'iterator' 这不是你如何实现'迭代器'

firstly, change the next() implementation: 首先,更改next()实现:

    ObjectIterator next() {
        return (*this = ObjectIterator(node->next));
    }

now, instead of returning the first element, return the header for iteration 现在,不是返回第一个元素,而是返回标题以进行迭代

ObjectIterator elements() {
    return ObjectIterator(header);
}

now you can use the syntax similar to the book and STL: 现在你可以使用类似书和STL的语法:

void print() {
    cout << "size is: " << size() << endl;

    ObjectIterator i = elements();

    while (i.hasNext()) {
        cout << i.next().element() << "\t";
    }
    cout << endl;
}

Notice that since you return the header, you dont have to check if(size() > 0) 请注意,既然返回标题,则不必检查(size()> 0)

EDIT 2: in next(), you can advance the node of iterator instead of iterator container itself 编辑2:在next()中,你可以推进迭代器的节点而不是迭代器容器本身

    ObjectIterator next() {
        node = node->next;
        return *this;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM