当前位置: 首页 > news >正文

C++中的泛型算法(三)

文章目录

  • 再探迭代器
    • 插入迭代器
    • iostream迭代器
      • istream_iterator
      • ostream_iterator
      • 使用流迭代器处理类类型
    • 反向迭代器
  • 算法命名规范
  • 特定容器算法

再探迭代器

除了为每个容器定义的迭代器之外,标准库在头文件iterator中还定义了额外几种迭代器:

  • 插入迭代器:绑定到一个容器上,可以用来向容器插入元素;
  • 流迭代器:绑定到输入或输出流上,用来遍历所关联的IO流;
  • 反向迭代器:向后移动,除了forward_list之外的标准库容器都有反向迭代器;
  • 移动迭代器:用来移动元素;

插入迭代器

插入迭代器绑定一个容器。当我们通过其进行赋值时会在容器指定位置插入一个元素。插入器有三种类型:

  • back——inserter:创建一个使用push_back的迭代器;
  • front_inserter:创建一个使用push——front的迭代器;
  • inserter:创建一个使用insert的迭代器,此函数接受第二个参数,该参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器之前。
auto it = inserter(c, iter);
*it = val; //插入后it更新指向插入位置后面的位置
//等价于
it = c.insert(it, val);
++it;std::list<int> lst1 = {1, 2, 3};
std::list<int> lst2 = {10, 20};std::copy(lst1.begin(), lst1.end(), std::back_inserter(lst2));
// lst2 = {10, 20, 1, 2, 3}std::copy(lst2.begin(), lst2.end(), std::inserter(lst1, lst1.begin()));
// lst1 = {10, 20, 1, 2, 3}

iostream迭代器

当创建一个流迭代器时,必须指定迭代器将要读写的对象类型。

istream_iterator

在这里插入图片描述

一个istream_iterator使用>>来读取流。因此要读取的类型必须定义了输入运算符。创建时可以绑定要一个流。未绑定时,可以当作尾后值:

istream_iterator<int> int_it(cin);
istream_iterator<int> int_eof;while(int_it != int_eof)
{//push_back旧值vec.push_back(*int_it++);
}//另外一种写法
vector<int> vec(int_it, int_eof);

结合算法使用

cout << accumulate(int_it, int_eof, 0);

ostream_iterator

一个ostream_iterator使用<<来读取流。因此要读取的类型必须定义了输出运算符。除了绑定输出流之外,还可以提供一个C风格的字符串。不允许空的或表示尾后位置的ostream_iterator。
在这里插入图片描述

ostream_iterator out_iter(cout, " "); //每个输出后加一个空格
//赋值语句实际上将元素写道cout
for(auto e : vec)*out_iter++ = e; //同out_iter = e;
cout << endl;

结合算法使用

//打印vec中的元素
copy(vec.begin(), vec.end(), out_iter);
cout << endl;

使用流迭代器处理类类型

#include <iostream>
#include <iterator>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>// 定义类
class Person {
public:std::string name;int age;Person() : name(""), age(0) {}Person(const std::string& n, int a) : name(n), age(a) {}
};// 输入运算符重载(用于 istream_iterator)
std::istream& operator>>(std::istream& is, Person& p) {return is >> p.name >> p.age;
}// 输出运算符重载(用于 ostream_iterator)
std::ostream& operator<<(std::ostream& os, const Person& p) {return os << p.name << " (" << p.age << ")";
}int main() {// 用 stringstream 模拟标准输入std::istringstream input("Alice 30\nBob 25\nCharlie 40\n");// 从输入流读取 Person 对象std::istream_iterator<Person> it(input);std::istream_iterator<Person> end;std::vector<Person> people(it, end);// 写入输出流std::ostream_iterator<Person> out(std::cout, "\n");std::copy(people.begin(), people.end(), out);cout << endl;return 0;
}

反向迭代器

反向迭代器就是在容器中从尾元素反向移动的迭代器。其递增递减操作的含义会颠倒过来,++it会移动到前一个元素,–iter会移动到后一个元素。

可以通过rbegin()、rend()、crbegin()、crend()等获取反向迭代器。这些成员函数指向容器尾元素和首前元素:
在这里插入图片描述
值得注意的是,反向迭代器需要支持递增和递减运算符,因此forward_list和流迭代器不能创建反向迭代器。

当我们通过反向迭代器找到元素位置,又想用普通迭代器完成后续操作,可以使用reverse_iterator的base成员:
在这里插入图片描述

[line.crbegin(), rcomma)(rcomma.base(), line.cend()]指向相同的元素的元素位置。其中rcommarcomma.base并不是指向一个位置,而是指向相邻的位置。

算法命名规范

  • 一些算法使用重载形式传递一个谓词:
unique(beg, end); //使用==比较元素
unique(beg, end, cmp); //使用cmp比较元素
  • _if版本:接受一个元素值得算法通常有一个不同名得版本
find(beg, end, val);
find_if(beg, end, pred) //查找第一个令pred为真得元素
  • _copy:区分拷贝版本和不拷贝版本
reverse(beg, end); //原容器逆序
reverse(beg, end, dest); //将元素逆序到dest
  • 同时支持_copy和_if
remove_if(v1.begin(), v1.end(), [](int i){ return i % 2;}); //删除奇数元素remove_copy_if(v1.begin(), v1.end(), back_insert(v2.begin()), [](int i){ return i % 2;}); //偶数复制到v2,v1不变

特定容器算法

与其他容器不同,list和forward_list因为是链表实现的,应该优先使用成员函数版本得算法而不是通用算法。
在这里插入图片描述
在这里插入图片描述

链表特有算法,无通用版本:
在这里插入图片描述

http://www.dtcms.com/a/316347.html

相关文章:

  • 智慧城市SaaS平台|市容环卫管理系统
  • 【PHP】对数据库操作:获取数据表,导出数据结构,根据条件生成SQL语句,根据条件导出SQL文件
  • nordic通过j-link rtt viewer打印日志
  • Unknown initial character set index ‘255’,Kettle连接MySQL数据库常见错误及解决方案大全
  • 心念之球:在意识的天空下
  • Gemini CLI最近更新
  • GitLab:一站式 DevOps 平台的全方位解析
  • 笔记学习杂记
  • fastgpt本地运行起来的 服务配置
  • iptables 里INPUT、OUTPUT、FORWARD 三个链(Chain)详解
  • 编程算法:技术创新与业务增长的核心引擎
  • 如何在虚拟机(Linux)安装Qt5.15.2
  • STM32 外设驱动模块一:LED 模块
  • 第13届蓝桥杯Scratch_选拔赛_初级组_真题2021年10月23日
  • 基于MATLAB实现的频域模态参数识别方法
  • SpringAI:AI基本概念
  • 基于ARM+FPGA多通道超声信号采集与传输系统设计
  • PCIe Base Specification解析(六)
  • 五、逐波限流保护电路-硬件部分
  • 从零搭建Cloud Alibaba (下) Sentinel篇
  • VUE-第二季-02
  • Sentinel全面实战指南
  • 制作一款打飞机游戏85:Hyper模式
  • JavaScript:Proxy 代理
  • 【数据结构初阶】--排序(三):冒泡排序,快速排序
  • 编码器模型和解码器模型解析
  • MongoDB学习专题(一)介绍安装基本操作
  • ✨OpenVoice 全流程实战:多语言语音合成系统安装与使用教程(附踩坑经验)
  • Makefile工具、双向链表
  • xshell、xftp使用案例