c++ - wie implementieren iterator für doppelt verkettete Liste

Ich bin mit diesem lehrbuch

http://cpp.datastructures.net

Kapitel 5 iterator-Verwendung:

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

hier ist, wie ich es umsetzen (die ObjectIterator Klasse)

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

    }

};

Wenn ich nicht der iterator verwendet wird, den folgenden code zum drucken ist richtig

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

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

        cout << endl;
    }

}

Wenn ich den iterator für die print-Funktion

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

einer der Knoten fehlt.
Das Buch ist nicht die richtige Art und Weise zu implementieren, die die iterator -

  • wenn Knoten ist der Letzte Knoten, Knoten->weiter ist der Anhänger, was bedeutet, dass hasNext() false ist
  • interessant, wenn ich zu entfernen dieses if-Anweisung, dann ist es richtig. Können Sie das erklären?
  • die print-Funktion ist falsch, denn der Letzte Artikel, den ich = ich.next hat keinen nächsten. der iterator ist richtig
InformationsquelleAutor OMGPOP | 2014-04-22
Schreibe einen Kommentar