写点什么

C++:使自定义类支持迭代器

  • 2024-09-11
    福建
  • 本文字数:1949 字

    阅读完需:约 6 分钟

概述


在 C++ 中,链表迭代器是一种用来遍历链表(如 std::list)元素的工具。链表是一种数据结构,其中每个元素(节点)包含一个数据值和一个指向下一个节点的指针。链表迭代器允许以类似于数组的方式访问链表中的元素,但不需要直接操作指针。


链表迭代器的作用


  • 访问元素:链表迭代器使你能够顺序访问链表中的每个元素,就像在数组中遍历元素一样。

  • 遍历链表:通过迭代器,你可以在链表中前进或后退,从而进行遍历操作。这使得在链表中执行各种操作(如查找、修改、删除等)变得简单而直观。

  • 抽象化操作:迭代器提供了一种统一的方式来访问不同类型的数据结构。无论是链表、数组还是其他容器,迭代器的使用方式大致相同,这让代码更加通用和易于维护。


使用示例


#include <iostream>#include <list> int main() {    std::list<int> myList = {1, 2, 3, 4, 5};        // 使用迭代器遍历链表    for (std::list<int>::iterator it = myList.begin(); it != myList.end(); ++it) {        std::cout << *it << " ";  // 输出链表元素    }        return 0;}
复制代码


为什么要为自己的类设置迭代器?


参考下述链表类


class List {public:    List(): head(new Node()) { }    ~List();     bool push(int x, int y);    // 在头部插入一个新坐标    bool pop(int x, int y);     // 查找指定坐标,并删除 private:    Node* head;};
复制代码


在该链表中,定义了pushpop两个方法,现假定,我们需要能够从第一个节点开始,逐步在外部调用链表的每一个节点,有一种简单的实现方法:


  • 定义search(int i)函数,从头开始,向后查询i个节点

  • 在外部采用 for 循环递增节点索引i


这里给出一个伪代码:


for (int i = 0; i < 10; ++i) {    Node cur = myList.search(i);    std::cout << cur << std::endl;}
复制代码


上述方法能够实现在外部对链表节点的遍历,但是,当索引较大时,鉴于每一次都需要从头访问至索引处,算力开销极大,因此我们必须采用更高效的方法。


如何为类设置迭代器方法?


观察标准库中迭代器的使用方法:


for (std::list<int>::iterator it = myList.begin(); it != myList.end(); ++it) {        std::cout << *it << " ";  // 输出链表元素}
复制代码


我们了解到需要实现如下内容:


  • 定义迭代器类,包含一个Node*类型的指针cur,指向当前元素。

  • 在链表类中,定义beginend函数,分别指向第一个元素和尾节点。

  • 定义!=运算符,以支持比较两个指针是否相同。

  • 定义++运算符,使得可以更便携的遍历节点。

  • 定义*运算符,使得可以采用指针方法访问到节点的值。


我们可以依次完成实现


class List {public:    List() : head(new Node()) { }    ~List();     bool push(int x, int y);    bool pop(int x, int y);     // 定义迭代器类    class Iterator {    public:        // 构造函数        Iterator(Node* node) : cur(node) {}        // 指针运算符        Cell& operator*() { return cur->cell; }        // 前置自增运算符        Iterator& operator++() {            if (cur) cur = cur->next;            return *this;        }        // 不等于运算符        bool operator!=(const Iterator& other) const { return cur != other.cur; }     private:        // cur字段        Node* cur;    }     // 分别定义begin()、end()方法    Iterator begin() const { return Iterator(head->next); }    Iterator end() const { return Iterator(nullptr); } private:    Node* head;};
复制代码


完成上述实现后,我们就可以使用迭代器方法快捷的访问类成员了。


#include <iostream>#include "list.h" int main() {    List ROI;    // 插入节点    ROI.push(0, 0);    ROI.push(0, 1);      ROI.push(0, 2);    ROI.push(0, 3);     for (List::Iterator it = ROI.begin(); it != ROI.end(); ++it) {        std::cout << *it << "\n";    }     return 0;}
复制代码


为什么将迭代器类Iterator嵌入链表类List中?


  • 封装性:将Iterator类作为LinkedList的嵌套类,可以更好地封装链表内部的实现细节。这样Iterator类只能访问LinkedList类的私有成员,而其他类不能直接访问Iterator类的内部细节。

  • 逻辑关联Iterator是专门用于遍历LinkedList的,因此将它放在LinkedList类内部有助于保持逻辑上的一致性和相关性。这样可以清晰地表示Iterator是为LinkedList量身定做的。

  • 简化访问:嵌套类可以访问外部类的私有成员。对于Iterator来说,它需要访问LinkedList的内部节点,因此将它作为嵌套类可以简化访问逻辑,而不需要额外的接口或方法来暴露链表的内部结构。


文章转载自:SXWisON

原文链接:https://www.cnblogs.com/SXWisON/p/18405181

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
C++:使自定义类支持迭代器_c++_不在线第一只蜗牛_InfoQ写作社区