You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链表end()迭代器实现困惑及operator--实现疑问

问题解答

1. 实现end()迭代器

end()代表尾后迭代器,它不需要指向真实内存位置,只需要一个能标识“超出最后一个元素”的状态即可。在链表中,这个状态可以直接用nullptr来表示:

实现代码

在List类中补充end()函数:

Iterator end()
{
    return Iterator(nullptr);
}

注意:尾后迭代器不允许被解引用,所以要给operator*加安全判断,避免空指针访问:

T& operator*()
{
    if (!m_node)
        throw std::runtime_error("Cannot dereference end iterator");
    return m_node->value;
}

另外,你的insert_back实际是头插逻辑(新节点放在链表头部),导致begin()返回的是链表尾节点,和标准容器begin()指向第一个元素的行为不符。建议修正为真正的尾插逻辑,同时给List类添加尾节点指针,避免每次找尾遍历:

// 修改List的成员变量
private:
    std::shared_ptr<Node<T>> m_head = nullptr;
    std::shared_ptr<Node<T>> m_tail = nullptr;

// 修正insert_back为尾插
void insert_back(const T value)
{
    auto node = std::make_shared<Node<T>>(value);
    if (!m_head)
    {
        m_head = node;
        m_tail = node;
    }
    else
    {
        m_tail->next = node;
        m_tail = node;
    }
}

// 此时begin()直接返回头节点
Iterator begin()
{
    return Iterator(m_head);
}

2. 实现operator--(反向迭代)

单链表节点只有next指针,没有前驱指针,实现反向迭代有两种方案:

方案一:改成双向链表(推荐)

给Node类添加前驱指针,这样迭代器可以直接通过前驱指针定位上一个节点,时间复杂度O(1):

template<typename T>
class Node
{
public:
    Node(const T _value) : value(_value) {}

    T value;
    std::shared_ptr<Node<T>> next = nullptr;
    std::weak_ptr<Node<T>> prev; // 用weak_ptr避免循环引用
};

// 修正insert_back,设置前驱指针
void insert_back(const T value)
{
    auto node = std::make_shared<Node<T>>(value);
    if (!m_head)
    {
        m_head = node;
        m_tail = node;
    }
    else
    {
        node->prev = m_tail;
        m_tail->next = node;
        m_tail = node;
    }
}

// 在Iterator中实现operator--
Iterator& operator--()
{
    if (m_node)
        m_node = m_node->prev.lock(); // 从weak_ptr转为shared_ptr
    return *this;
}

// 后置--运算符
Iterator operator--(int)
{
    Iterator temp = *this;
    --(*this);
    return temp;
}

方案二:单链表下的低效实现(不推荐)

如果坚持用单链表,只能通过遍历链表找到当前节点的前驱,时间复杂度O(n),仅适合小链表场景:

// 修改Iterator,持有链表头指针
class Iterator
{
public:
    Iterator(std::shared_ptr<Node<T>> node, std::shared_ptr<Node<T>> head) 
        : m_node(node), m_head(head) {}

    Iterator& operator--()
    {
        if (!m_node)
        {
            // end()迭代器--后指向尾节点
            m_node = m_head;
            while (m_node && m_node->next)
                m_node = m_node->next;
            return *this;
        }
        if (m_node == m_head)
        {
            // 头节点的前一个是end()
            m_node = nullptr;
            return *this;
        }
        // 遍历找前驱节点
        auto prev = m_head;
        while (prev && prev->next != m_node)
            prev = prev->next;
        m_node = prev;
        return *this;
    }

private:
    std::shared_ptr<Node<T>> m_node;
    std::shared_ptr<Node<T>> m_head; // 保存链表头指针
};

// 修改List的begin()和end(),传入头指针
Iterator begin()
{
    return Iterator(m_head, m_head);
}

Iterator end()
{
    return Iterator(nullptr, m_head);
}

内容的提问来源于stack exchange,提问作者KcFnMi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 01:43:14