排序列表类 cpp 中的 const_iterator 实现

问题描述

我正在尝试制作一个 const_iterator,但我在理解它时遇到了一些麻烦。我尝试更改内容以使其正常工作,但无法编译。有人可以帮我理解我做错了什么吗? 我的代码看起来像那样 -

#include <iostream>
#include <cstring>
#include <string>
#include <functional>

#include "dummy.h"
using namespace std;

#ifndef SORT_H
#define SORT_H

template <class T>
class LinkedList {
    struct Node {
        Node(const T &in) : data(in) {}
        T data;
        Node * next;
    };

    Node * head;

public:
    LinkedList() {
        head = nullptr;
    }
    LinkedList(T value) {
        head = new Node(value);
    }

    ~LinkedList() {
        while(head != nullptr) {
            Node * curr = head -> next;
            delete head;
            head = curr;
        }
    }

    class const_iterator
    {
        Node* m_ptr; // pointer to current node in the list
        bool operator != (const const_iterator other) const {
        return m_ptr != other.m_ptr;
    }
    public:
        const_iterator() {
            m_ptr = nullptr;
        }
        const_iterator(Node * node) {
            m_ptr = node;
        }
        const_iterator(const const_iterator &it){
            m_ptr = it.m_ptr;
        }
        const_iterator& operator =(const_iterator it) {
            std::swap(it.m_ptr,m_ptr);
            return *this;
        }
        const_iterator& operator ++ () {
            if (m_ptr == nullptr) {
                throw out_of_range("out of range");
            }
            m_ptr = m_ptr -> next;
            return *this;
        }
        const_iterator operator ++ (T) {
            if (m_ptr == nullptr) {
            throw out_of_range("out of range");
            }
            const_iterator temp(*this);
            m_ptr = m_ptr -> next;
            return temp;
        }
        bool operator == (const const_iterator other) const {
            return m_ptr == other.m_ptr;
        }

        T& operator*() const {
            return *m_ptr;
        }
        operator bool() {
            return m_ptr != nullptr;
  
        };

    bool is_in_list(LinkedList<T>::const_iterator it){
        Node * curr = head;
        while(curr != nullptr) {
            if (curr == it){
                return true;
            } else {
                curr = curr->next;
            }
        }
        return false;
    }

    LinkedList& operator =(LinkedList list) {
        std::swap(list.head,head);
        return *this;
    }

    Node * nodecopy(Node * head) {
        if (head == nullptr) {
            return nullptr;
        }
        Node * copied_node = new Node(head -> data);
        copied_node -> data = head -> data;
        copied_node -> next = nodecopy(head -> next);
        return copied_node;
    }

    LinkedList(const LinkedList &list){
        head = nodecopy(list.head);
    }


    template<typename B>
    LinkedList filter(LinkedList &list,B pred) {
        LinkedList <T> new_list(list);
        Node * curr = list.head;
        while (curr) {
            if (!(pred(curr -> data))) {
                new_list.remove(curr -> data);
            }
            curr = curr -> next;
        }
        std::cout << "Getting out of filter" << std::endl;
        return new_list;
    }

    template<typename A>
    LinkedList apply(A func) {
        LinkedList <T> new_list;
        Node * curr = head;
        while (curr) {
            new_list.insert(func(curr -> data));
            std::cout << "Putting into new list: " << func(curr -> data) << std::endl;
            curr = curr -> next;
        }
        std::cout << "Getting out of apply" << std::endl;
        return new_list;
    }

    int length() {
//        std::cout << "DEBUG length 1" << std::endl;
        int counter = 0;
        Node * tmp = head;
//        std::cout << "DEBUG length 2" << std::endl;
        while( tmp != nullptr ) {
//            std::cout << "DEBUG length 3" << std::endl;
            counter++;
            tmp = tmp -> next;
        }
        return counter;
    }

    void insert(T value) {
        // Add first node
        if (head == nullptr) {
            std::cout << "Add first node" << std::endl;
            head = new Node(value);
            head->next = nullptr;
            return;
        }

        Node *curr = head;
        // check if should be new head (when new value smaller than current head) -> add new head
        if (value <= head->data) {
            // add new head
            std::cout << "add new head" << std::endl;
            Node * new_head = new Node(value);
            new_head -> next = head;
            head = new_head;
            return;
        }

        while (curr != nullptr) {
            if (curr->next == nullptr && value >= curr->data) {
                // add new tail
                std::cout << "add new tail" << std::endl;
                Node * new_node = new Node(value);
                curr -> next = new_node;
                new_node -> next = nullptr;
                return;
            } else if (value >= curr->data && value <= curr->next->data) {
                // add new node between those two
                std::cout << "add new node between those two" << std::endl;
                Node * new_node = new Node(value);
                Node * temp_ptr = curr -> next;
                curr -> next = new_node;
                new_node -> next = temp_ptr;
                return;
            } else {
                curr = curr->next;
            }
        }
    }

    void remove(const_iterator it) {
        // Todo: Check if delete all accurancies
        if (!is_in_list(it)){
            return;
        }

        // handle the head
        if (head == it) {
            if (head->next != nullptr) {
                // head is not single node
                Node * temp_ptr = head->next;
                delete head;
                head = temp_ptr;
                return;
            } else {
                // head is single node
                delete head;
                head = nullptr;
                return;
            }
        }

        Node * curr = head;
        Node * prev = head;
        while (curr != nullptr){
            if (curr == it){
                // as we are already handled the head case,// at this point we kNow that curr != head.
                prev->next = curr->next;
                delete curr;
                return;
            } else {
                prev=curr;
                curr=curr->next;
            }
        }

    }

    void print() {
        Node * curr = head;
        while (curr != nullptr) {
            cout << curr -> data << endl;
            curr = curr -> next;
        }
    }

    Node * begin() const {
        return head;
    }
    Node * end() const {
        Node * curr = head;
        while (curr->next != nullptr){
           curr = curr->next;
        }
        return curr;
    }
};


#endif

我的主要看起来像那样-

#include <iostream>
#include "sortedList.h"
#include "dummy.h"

bool func(Dummy num) {
    int number = num.get();
    if (number % 2 != 0) {
        return false;
    }
    return true;
}

string getLen(string str)
{
    return std::to_string(str.length());
}

using std::string;

int main() {
    std::cout << "Hello,World!" << std::endl;

        LinkedList<string> lst1 = LinkedList<string>();
        lst1.insert("Charlie");
        lst1.insert("Bob");
        lst1.insert("Alice");
        lst1.insert("Donald");
        lst1.print();
        LinkedList<string> lst2 = lst1;
        lst2 = lst2.apply(getLen);
        lst2.print();
        LinkedList<string>::const_iterator it = lst2.begin();
        cout << *it << endl << endl;
        ++it;
        lst2.remove(it);
        lst2.print();

    return 0;
}

我收到的错误信息是- (因为太长了,不全都在这里了)

    In file included from C:\Users\User\CLionProjects\ex2.2\main.cpp:2:
C:\Users\User\CLionProjects\ex2.2\sortedList.h: In instantiation of 'class LinkedList<std::__cxx11::basic_string<char> >::const_iterator':
C:\Users\User\CLionProjects\ex2.2\main.cpp:40:44:   required from here
C:\Users\User\CLionProjects\ex2.2\sortedList.h:79:24: error: postfix 'LinkedList<T>::const_iterator LinkedList<T>::const_iterator::operator++(T) [with T = std::__cxx11::basic_string<char>]' must have 'int' as its argument
         const_iterator operator ++ (T) {
                        ^~~~~~~~
C:\Users\User\CLionProjects\ex2.2\sortedList.h: In instantiation of 'T& LinkedList<T>::const_iterator::operator*() const [with T = std::__cxx11::basic_string<char>]':
C:\Users\User\CLionProjects\ex2.2\main.cpp:41:18:   required from here
C:\Users\User\CLionProjects\ex2.2\sortedList.h:92:21: error: invalid initialization of reference of type 'std::__cxx11::basic_string<char>&' from expression of type 'LinkedList<std::__cxx11::basic_string<char> >::Node'
             return *m_ptr;
 

解决方法

我做错了什么?

self_type operator++() { self_type i = *this; ptr_++; return i; }

这行不通。 ptr_++ 会将指针移动到 array 的下一个元素...除了在这种情况下没有数组。您不是在为数组编写迭代器,而是在为链表编写迭代器。

您需要一个指向节点的指针,而不是指向元素的指针。要移动到下一个节点,您需要 ptr = ptr->next


至于编译错误,看错误信息,错误在哪里。您还没有显示 return *head; 的位置,但让我们看看另一个:

Node * head;
...
LinkedList<T>::const_iterator it
...
if (head == it) {

您正在将指向节点的指针与迭代器进行比较。为什么你认为这会奏效?你期望结果是什么?错误的解决方法是不这样做。