10.2 初始泛型算法

news2024/11/15 8:28:20

文章目录

    • 只读算法
      • find()
      • count()
      • accumulate()
      • equal()
    • 写容器元素算法
      • fill()
      • fill_n()
      • back_inserter()
      • copy()
      • copy_backward()
      • replace()
      • replace_copy()
      • next_permutation()
      • prev_permutation()
    • 重排容器元素算法
      • sort()
      • unique()
      • stable_sort()

除了少数例外,标准库算法都对一个范围内的元素进行操作。我们将此元素范围称为“输入范围”。接受输入范围的算法总是使用前两个参数来表示此范围,两个参数分别是指向要处理的第一个元素和尾元素之后位置的迭代器。

虽然大多数算法遍历输入范围的方式相似,但它们使用范围中元素的方式不同。理解算法的最基本的方法就是了解它们是否读取元素、改变元素或是重排元素顺序。

只读算法

只可以操作容器元素,不可以改变容器内的值
因为是只读,所以建议使用只读迭代器(cbegin()、cend())

常见的只读算法:

> find
> count
> accumulate
> equal 

find()

/*定义 find(参数1(起始迭代器),参数2(尾迭代器),参数3(查找的元素))
功能:遍历一个范围中是否包含某元素
参数:前2个参数是一个迭代器范围或者指针范围。第3个参数是要查找的元素
返回值:成功返回要查找的元素所在的迭代器。失败返回参数2*/

int arr[] = { 1,2,3,4,5 };
int value = 3;
auto result = find(arr + 1, arr + 3, value);
cout << "The value "<<value<<((result == arr + 3)
	?" is not present":"is present")<< endl;

count()

/*count(参数1(起始迭代器),参数2(尾迭代器),参数3(查找的元素))
参数:前2个参数是一个迭代器范围或者指针范围。第3个参数是要计数的元素
功能:返回元素在指定迭代器范围内出现的次数
返回值:成功返回出现的次数,没有返回0*/

list<int> li{ 1,2,3,66,66,66,100 };
cout <<"The 66 count is:" 
	<<count(li.cbegin(),li.cend(),66)<< endl;

accumulate()

/*accumulate(vec.cbegin(),vec.cend(),0)
头文件:numeric
功能:将指定范围内的元素进行和运算,参数3为和运算的初始值
返回值:返回和运算的结果
注意:此函数操作的元素必须能够与+运算符进行操作,实际上是根据第三个参数的类型决定函数使用哪个加法运算符及返回值类型。*/

//计算li元素的和,和的初始值为0
list<int> li{ 1,2,3 };
cout <<"The sum is:" <<accumulate(li.cbegin(),li.cend(),0)<< endl; //6

//使用string时,必须显示地调用,不能够直接使用字符串,因为这样会被accumulate函数认为是一个const char*对象而出错,因为const char*对象是没有+这种运算的。
ist<string> li{"A","B","C"};
cout <<accumulate(li.cbegin(),li.cend(),string("String:"))<< endl; //String:ABC

//如果想要进行别的运行,例如乘、除等,可以使用参数4.例如下面是对一个数组内的元素进行乘操作(备注:初始化不要填0,否则结果就为0)
int *p = new int[4] {1, 2, 3, 4};
cout << accumulate(p, p + 4, 1,multiplies<int>()) << endl; //24

equal()

/*equal(vec1.cbegin(),vec1.cend(), vec2.cbegin())
功能:用来比较两个指定范围内的元素是否都是相同的值(常来比较两个容器是否相同)
参数:参数1和参数2指定一个容器的范围。参数3指定另一个容器的开始范围
比较规则:将参数1和2指定的范围内的所有元素,查看这些元素是否与参数3所指定的另一个容器的开始处是否都存在(不一定要个数都相同,只要容器1的指定开始的元素在容器2中都要一一对应)
返回值:都相同返回1。不相同返回0
因为equal调用迭代器完成操作,所以equal可以用来比较两个不同类型的容器。例如vector<string>和list<const char*>可以进行比较*/

vector<int> vec1{ 2,3};
vector<int> vec2{ 1,2,3,4 };
cout << equal(vec1.cbegin(),vec1.cend(), vec2.cbegin())<< endl; //0

写容器元素算法

将新值赋予给序列中元素,此时要确保序列原大小不小于算法要求写入的元素数目。(算法不会改变容器大小)
迭代器不会检查写入数据位置大小是否足够大

常见的写容器算法:

> fill(beg,end,val) //将val赋给输入序列每个元素
> fill_n(dest,n,val)//从dest开始n个元素赋值为val
> back_inserter
> copy
> copy_backward
> replace
> replace_copy
> next_permutation
> prev_permutation

fill()

/*fill(参数1,参数2,参数3)
用来改变指定位置处的元素
参数:参数1、2指定容器的范围,参数3位要设置的值*/

vector<int> vec{ 1,2,3,4,5,6 };
fill(vec.begin(), vec.begin()+vec.size()/2, 66); //将vec的前半部分元素变为66

for (auto v = vec.cbegin(); v != vec.cend(); v++)
	cout << *v << endl;

fill_n()

fill_n(参数1,参数2,参数3)
用来将指定数量的元素变为某个值
参数:参数1为迭代器起始位置。参数2为要改变的元素个数。参数3为要设定的值
注意:要注意参数2的设定,不能超出容器的大小,也不能对空容器操作

vector<int> vec{ 1,2,3,4,5,6 };

fill_n(vec.begin(), 3, 66); //将vec的前3个元素变为66
for (auto v = vec.cbegin(); v != vec.cend(); v++)
	cout << *v << endl;

fill_n(vec.begin(), vec.size(), 66); //将vec全部变为66
for (auto v = vec.cbegin(); v != vec.cend(); v++)
	cout << *v << endl;

back_inserter()

back_inserter(参数)
又名插入迭代器
参数:为一个容器的引用
返回值:返回与该容器绑定的插入迭代器,或者可以理解为back_inserter函数返回值是指向给定容器尾部的迭代器。
功能:常用来返回一个容器的迭代器,然后对此迭代器进行操作
当我们通过返回的插入迭代器赋值时,会自动调用push_back将一个具有给定值的元素添加到容器中
头文件iterator

vector<int> vec; //空容器

auto it = back_inserter(vec); //返回vec的第一个迭代器
*it = 42; //此时vec有了一个元素,值为42

copy()

copy(参数1,参数2,参数3)
将参数12指定范围的元素拷贝给参数3指定的容器
参数:参数12为一个容器的范围。参数3要接受拷贝的容器起始位置
注意:参数3要有足够的空间保存拷贝的数据
返回值:返回拷贝目的位置的迭代器值

int arr1[] = { 1,2,3 };
int arr2[sizeof(arr1)/sizeof(*arr1)];

auto ret = copy(begin(arr1), end(arr1), arr2); //将数组1拷贝给数组2。ret为arr2数组最后元素的下一个位置

for (auto i = 0; i < sizeof(arr2) / sizeof(*arr2); i++) {
    cout << arr2[i]<< endl;
}

copy_backward()

/*copy_backward(参数1,参数2,参数3)
该函数与copy的不同之处在于:
copy是从第一个元素开始拷贝,而copy_backward是从最后一个元素开始拷贝
copy的第3个参数是接受拷贝的容器起始位置,而copy_backward是目的序列的结束迭代器
会复制前两个迭代器参数指定的序列。第三个参数是目的序列的结束迭代器
值得注意的是arr1的end和arr2的end元素都是不进行赋值的*/

	int arr1[] = { 1,2,3 };
	int arr2[sizeof(arr1) / sizeof(*arr1)];

	auto ret = copy_backward(begin(arr1), end(arr1), end(arr2)); //将数组1拷贝给数组2。ret为arr2数组最后元素的下一个位置

	for (auto i = 0; i < sizeof(arr2) / sizeof(*arr2); i++) {
		cout << arr2[i] << endl;
	}

replace()

/*replace(参数1,参数2,参数3,参数4)
将指定范围内指定的元素替换为另一个值
参数:1、2指定替换的范围。3:目标值,4:替换后的值
头文件algorithm*/

vector<int> vec{ 1,0,0,0,5 };
replace(vec.begin(), vec.end(), 0,66); //将vec中为0的全部替换为66

for (auto v = vec.cbegin(); v != vec.cend(); v++) {
	cout << *v << endl;
}

replace_copy()

/*replace_copy()
此函数会保留原容器不变,然后将替换后的结果保存在另一个容器中
参数:参数1,2位为要替换的范围。参数3位另一个容器的起始位置。参数4目标值。参数5替换后的值
头文件algorithm*/

vector<int> vec{ 1,0,0,0,5 };
vector<int> vec2;

replace_copy(vec.begin(), vec.end(),back_inserter(vec2), 0,66); //vec的元素保持不变,vec2为替换后的值
	
for (auto v = vec2.cbegin(); v != vec2.cend(); v++) {
    cout << *v << endl;
}

next_permutation()

/*next_permutation(参数1,参数2)
功能:对一个迭代区间的数值进行全排列
返回值:会根据前面next_permutation函数的调用,当操作的区间不存在下一个排列时,函数返回false;否则如果可以继续进行全排列,那么就返回true

函数原型
#include <algorithm>
bool next_permutation(iterator start,iterator end)*/

int *p = new int[3] {1, 2, 3};
do {
    for (int i = 0; i < 3; ++i){
        cout << p[i];
    }
    cout << endl;
} while (next_permutation(p, p + 3));

输出结果:
在这里插入图片描述

prev_permutation()

/*prev_permutation()
与next_permutation的功能显示,区别就是prev_permutation是求当前排列的前一个排列,而next_permutation是求当前排列的下一个排列*/

举个例子进行分析:

#include<iostream>
#include<algorithm>
using namespace std;
int a[] = {2, 1, 3};
int main(){
    /*正常的排序:
    1 2 3
    1 3 2
    2 1 3
    2 3 1
    3 1 2
    3 2 1
    */
    if(next_permutation(a, a + 3)){ // 如果下一个字典序全排列存在则输出
        cout << a[0] << ' ' << a[1] << ' ' << a[2] << endl;
    }
    /*
    输出:
    2 1 3
	2 3 1
	3 1 2
	3 2 1
	*/
    if(prev_permutation(a, a + 3)){ // 如果上一个字典序全排列存在则输出
        cout << a[0] << ' ' << a[1] << ' ' << a[2] << endl;
    }
    /*
    输出:
    2 3 1
    1 3 2
    */
}

也就是说如果我们想要全排列,就需要先将此容器进行大小排序,从小到大进行排序之后,再进行next_permutation.

重排容器元素算法

某些算法会重排容器中元素的顺序,一个明显的例子是sort。调用sort 会重排输入序列中的元素,使之有序,它是利用元素类型的<运算符来实现排序的。

常见的重排容器元素的算法:

sort(beg,end); //利用<运算符实现排序
unique(beg,end); //重排,不重复元素排在vector开始部分,返回不重复区域之后一个位置的迭代器
stable_sort(beg,end)

sort()

/*sort(beg,end)
将容器内的元素按照运算符“<”的规则排序,从小到大
参数:一个容器的迭代器范围*/

vector<int> vec{ 1,4,2,8,4,1 };
sort(vec.begin(), vec.end()); //将vec的值从小到大排序

for (auto v = vec.cbegin(); v != vec.cend(); v++) {
    cout << *v << endl;
}

unique()

/*unique()
相邻之间如果有重复相同的元素,则删除重复的元素只保留一个
参数:一个容器的迭代器范围
返回值:返回删除重复元素之后的最后一个元素的后一个位置
注意(重点):虽然删除了元素,但是容器的大小依然没有变,迭代器也没有变。所有变为迭代器时一定要注意*/

vector<int> vec{ 1,1,2,3,4,4,4,5,1 };
auto end_unique = unique(vec.begin(), vec.end());

//for循环时使用unique的返回值,如果使用vec.cend(),那么会打印后面没有元素位置的乱值
for (auto v = vec.cbegin(); v != end_unique; v++) { 
	cout << *v << endl;
}

stable_sort()

/*stable_sort(beg,end)
与sort()一样也是排序,默认也使用“<”对元素进行排序,而且可保证相等元素的原本相对次序在排序后保持不变*/

vector<int> vec{ 1,10,88,2,100,88,4,1 };
stable_sort(vec.begin(), vec.end());

for (auto v = vec.cbegin(); v != vec.cend(); v++) {
    cout << *v << " ";
}
cout << endl;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/171253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pandas数据聚合与分组运算

文章目录数据聚合与分组运算分组与聚合的原理通过groupby()方法将数据拆分成组按列名进行分组按Series对象进行分组按字典进行分组按函数进行分组数据聚合与分组运算 对数据集进行分组并对各组应用一个函数&#xff08;无论是聚合还是转换&#xff09;&#xff0c;通常是数据分…

哈佛结构和冯诺依曼结构?STM32属于哈佛结构还是冯诺依曼结构?

现代的CPU基本上归为冯诺伊曼结构&#xff08;也成普林斯顿结构&#xff09;和哈佛结构。 冯诺依曼体系 冯诺依曼体系结构图如下 冯诺依曼结构也称普林斯顿结构&#xff0c;是一种将程序指令存储器和数据存储器合并在一起的存储器结构。数据与指令都存储在同一存储区中&…

大数据技术架构(组件)5——Hive:流程剖析2

1.1.2、Stage division&#xff08;不够细致&#xff0c;需要例子&#xff09;Stage理解&#xff1a;结合对前面讲到的Hive对查询的一系列执行流程的理解&#xff0c;那么在一个查询任务中会有一个或者多个Stage.每个Stage之间可能存在依赖关系。没有依赖关系的Stage可以并行执…

IIS部署应用程序连接 LocalDB 数据库

使用.net core框架创建ASP.NET Core API应用程序&#xff0c;利用Entity Framework core实体进行MS LocalDB数据库进行连接操作&#xff08;增/删/改/查运行&#xff09;。 问题&#xff1a; 在Visual Studio 2022 开发工具可以正常运行 Web API 应用程序连接 LocalDB 数据库…

R语言基于poLCA包进行潜类别分析

潜在类别分析是一种分析多元分类数据的统计技术。当观测数据以一系列分类响应的形式出现时- -例如&#xff0c;在民意调查、个人层面的投票数据、人与人之间可靠性的研究或消费者行为和决策中- -通常感兴趣的是调查观测变量之间的混淆来源&#xff0c;识别和表征相似案例的集群…

初步了解高性能队列——Disruptor(Java)

高性能队列——Disruptor ① 概述 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列&#xff0c;研发的初衷是解决内部的内存队列的延迟问题&#xff0c;而不是分布式队列。基于Disruptor开发的系统单线程能支撑每秒600万订单&#xff0c;2010年在QCon演讲后&#xff0c…

DevOps利器之二(Git,Gitlab)

一、背景Git&#xff0c;Gitlab在DevOps中主要解决持续集成源码管控部分&#xff0c;本文主要从基本概念&#xff0c;实施部署两部分介绍。二、git概述https://git-scm.com/book/zh/v2 --推荐官方电子书 Git - 它是一个源代码分布式版本控制系统&#xff0c;可让开发人员在本地…

行业分享:锂电池4大生产难题,视觉检测即可有效解决

导语&#xff1a;机器视觉检测已在锂电池生产的各个环节中&#xff0c;为产品产量与质量提供可靠保障。维视智造作为锂电池视觉检测系统提供商&#xff0c;为企业提供专业、系统、稳定的锂电行业解决方案&#xff0c;可保证0漏检&#xff0c;确保安全生产&#xff0c;全面提升生…

Java总结(运算符)

1.算数运算符short s12;s1s12; &#xff08;编译不能运行)short s12;s1 2 ; (编译能运行&#xff0c;不改变变量本身的数据类型)2.逻辑运算符区分&和&&相同点&#xff1a;运算结果相同&#xff1b;当符号左边是true时&#xff0c;两者都会执行符号右边的运算不同点…

医疗数据安全实力派 | 美创科技品牌案例入选《2022年医疗行业网络安全报告》

近日&#xff0c;网络安全产业机构“数说安全”正式发布《2022年医疗行业网络安全报告》&#xff08;以下简称“报告”&#xff09;。报告对我国医疗行业信息化现状和政策、医疗行业市场发展、医疗行业需求侧及供给侧进行深度剖析。美创科技作为专业数据安全代表厂商入选医疗网…

你应该知道的机器学习模型部署细节和实施步骤

机器学习操作 (MLOps&#xff0c;Machine Learning Operations ) 是“机器学习”和“工程”的组合&#xff0c;涵盖了与生产 ML 生命周期管理有关的所有内容。 ML模型生命周期可大致分为三个阶段 文章目录技术交流设计模型开发操作步骤1&#xff1a;确定部署环境命令行终端Cond…

Arduino开发ESP8266网页服务器控制LED灯

根据板卡原理RGB三色LED对应引脚&#xff1a;int LEDR12、int LEDG14、int LEDB13;设置串口波特率为115200Serial.begin(115200);源代码如下所示&#xff1a;3.1添加头文件#include <ESP8266WiFi.h> // 提供 Wi-Fi 功能的库#include <ESP8266WebServer.h> // 提供网…

Solidity 中的数学(第 3 部分:百分比和比例)

本文是关于在 Solidity 中进行数学运算的系列文章中的第三篇 。 这次的主题是&#xff1a;百分比和比例。 介绍 金融数学从百分比开始。y的x百分比是多少&#xff1f;y占x的多少百分比&#xff1f;我们都知道答案&#xff1a;y的x百分比是x y 100&#xff0c;y是y 10…

GPIO 应用

应用层如何控制 GPIO&#xff0c; 譬如控制 GPIO 输出高电平、或输出低电平。应用层如何操控 GPIO与 LED 设备一样&#xff0c; GPIO 同样也是通过 sysfs 方式进行操控&#xff0c;进入到/sys/class/gpio 目录下。可以看到该目录下包含两个文件 export、 unexport 以及 5 个 gp…

面试 | 百度测试开发岗位面试题目回顾

一面题目 二面题目 面试经历详情 在招聘网站投递简历后&#xff0c;收到面试通知信息&#xff08;如下图&#xff0c;为保护个人隐私&#xff0c;面试岗位、地点、时间等隐去&#xff09;。虽然写的是高级测试开发工程师&#xff0c;但是面试官说他们部门的测试不一定都要写框架…

【年更分享】带你看看前端生态圈的技术趋势 state-of-css 2022 state-of-js 2022详细解读

各位前端开发者们大家好&#xff0c;我又来给大家解读最新一年的 state-of-css & state-of-js 技术调查了&#xff01; 往年的 state-of-css 和 state-of-js 的解读&#xff1a; state-of-js 2020 详细解读 state-of-js 2021 详细解读 state-of-css 2021 详细解读 一、写…

php 断点调试 PHPStorm Xdebug helper

安装与使用php的xdebug扩展 浏览器访问只包含<?php phpinfo();的php文件&#xff0c;查看php详情。页面搜索是否安装了xdebug扩展。 如未安装&#xff0c;则访问&#xff1a;xdebug安装向导&#xff0c;将phpinfo()的输出页面复制到此文本框中&#xff0c;点击页面下方的“…

Ubuntu18.04安装Anaconda

Ubuntu18.04安装Anaconda 文章目录Ubuntu18.04安装Anaconda1 下载Anaconda2 安装annaconda3 创建新环境conda环境配置指令pip环境&#xff0c;阿里源切换虚拟环境pytorch 安装不成功pycharm切换python版本4 国内conda源5 卸载anacondaReference1 下载Anaconda 下载Anaconda3-2…

Zerotier免费的虚拟局域网

Zerotier介绍 Zerotier是一款用于构建异地虚拟局域网的工具。 通过网页后台创建虚拟网络并进行管理。 通过电脑上的Zerotier客户端连接各个异地电脑到虚拟局域网&#xff0c;从而实现组网。 由后台分配虚拟ip&#xff0c;并且各个异地电脑可以通过虚拟IP对同一虚拟局域网下的其…

零基础学SQL(九、分组 GROUP BY)

目录 前置建表 ​编辑 一、分组的概念 二、分组案例 三、分组的过滤HAVING子句 前置建表 CREATE TABLE student (id int NOT NULL AUTO_INCREMENT COMMENT 主键,code varchar(255) NOT NULL COMMENT 学号,name varchar(255) DEFAULT NULL COMMENT 姓名,sex enum(男,女) DEF…