概述


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

C++:使自定义类支持迭代器的更多相关文章

  1. 自定义类支持foreach

    建议使用yield语句简化迭代 using System; using System.Collections; namespace 自定义类实现foreach { class A { int[] w; ...

  2. 使自定义事件支持多绑定 js

    <script language="JavaScript" type="text/javascript"> <!-- //定义类class1 ...

  3. [Yii2.0] 以Yii 2.0风格加载自定义类或命名空间 [配置使用Yii2 autoloader]

    Yii 2.0最显著的特征之一就是引入了命名空间,因此对于自定义类的引入方式也同之前有所不同.这篇文章讨论一下如何利用Yii 2.0的自动加载机制,向系统中引入自定义类和命名空间.本文旨在抛砖引玉,如 ...

  4. 自定义类在PropertyGrid上的展示方法

    自定义类在PropertyGrid上的展示方法 零.引言 PropertyGrid用来显示某一对象的属性,但是并不是所有的属性都能编辑,基本数据类型(int, double等)和.Net一些封装的类型 ...

  5. java学习--自定义类的实例的大小比较和排序

    我们知道Object类有一个equals方法,用于比较两个对象是否相等 我们只要在自定义类中重写了equals方法(若不重写就是比较两个实例的地址,相当于==)就可以用来比较该类的两个实例是否相等 问 ...

  6. python面向对象反射-框架原理-动态导入-元类-自定义类-单例模式-项目的生命周期-05

    反射 reflect 反射(reflect)其实是反省,自省的意思 反省:指的是一个对象应该具备可以检测.修改.增加自身属性的能力 反射:通过字符串获取对象或者类的属性,进行操作 设计框架时需要通过反 ...

  7. cocos2dx-3.x 导出自定义类到 lua 过程详解

    转载请注明出处:http://www.cnblogs.com/Ray1024 一.简介 最近正在学习cocos2d中的lua游戏开发,因为lua开发的热更新特性,大家开发游戏好像都会优先选择lua作为 ...

  8. VBA中自定义类和事件的(伪)注册

    想了解一下VBA中自定义类和事件,以及注册事件处理程序的方法. 折腾了大半天,觉得这样的方式实在称不上“注册”,所以加一个“伪”字.纯粹是瞎试,原理也还没有摸透.先留着,有时间再接着摸. 做以下尝试: ...

  9. Adobe Edge Animate –修改Edge Commons Spotlight功能,使之能支持播放中国网站视频

    Adobe Edge Animate –修改Edge Commons Spotlight功能,使之能支持播放中国网站视频 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权 ...

  10. Extjs-4.2.1(二)——使用Ext.define自定义类

    鸣谢:http://www.cnblogs.com/youring2/archive/2013/08/22/3274135.html --------------------------------- ...

随机推荐

  1. SpringBoot中使用Servlet3.0注解开发自定义的拦截器

    使用Servlet3.0的注解进行配置步骤 启动类里面加@ServletComponentScan,进行扫描 新建一个Filter类,implements Filter,并实现对应的接口 @WebFi ...

  2. Oracle自定义数据类型

    1 CREATE OR REPLACE FUNCTION split(p_str IN clob, 2 p_delimiter IN VARCHAR2 default (',') --分隔符,默认逗号 ...

  3. 洛谷P1176

    #include<iostream> #include<utility> using namespace std; typedef long long ll; #define ...

  4. LabVIEW图标编辑器中的文本变得模糊

    问题详述 在LabVIEW图标编辑器中将文本添加到VI图标时,如果我将字体大小设置为小于10,文本会变得模糊.当字体大小设置为大于11时,文本会正常地显示,但是字体则变得太大而无法放入图标中. 真难看 ...

  5. 使用 Node.js 和 Express 构建基本的 Web API

    使用 Node.js 和 Express 构建 Web API Web API Node.js 中的 http 模块 创建 Express 框架 Web 应用程序 Express 框架 Express ...

  6. Flink 内存配置学习总结

    设置进程内存(Process Memory) Apache Flink通过严格控制其各种组件的内存使用,在JVM之上提供高效的工作负载. 配置总内存(Total Memory) Flink JVM进程 ...

  7. 关于使用c++制作蓝牙连接,Windows版本

    1 #define _CRT_SECURE_NO_WARNINGS 2 #pragma warning(disable : 4995) 3 #include <iostream> 4 #i ...

  8. 2个月搞定计算机二级C语言——真题(1)解析

    1. 前言 大家好,我是梁国庆. 这段时间将持续发布计算机二级 C 语言真题的解析,想要同步练习,需要资源包的朋友可以跳转免费获取--<3个月搞定计算机二级C语言--准备工作>. 现在恐怕 ...

  9. Jmeter循环控制器

    循环控制器(Loop Controller),循环控制器会将该控制器里面所有请求循环运行指定次数 循环次数:勾选"永远"则程序会一直循环运行不会停止,不勾选"永远&quo ...

  10. 《Python数据可视化之matplotlib实践》 源码 第一篇 入门 第二章

    图 2.1 import matplotlib as mpl import matplotlib.pyplot as plt mpl.rcParams['font.sans-serif']=['Sim ...