【第十天】C++函数对象/仿函数、谓词、适配器及常见algorithm算法

一、函数对象

        重载了函数调用运算符() 实例化的对象函数对象,也叫仿函数。

  • 如果函数对象 有一个参数 叫:元函数对象/仿函数
  • 如果函数对象 有二个参数 叫:元函数对象/仿函数
  • 如果函数对象 有三个及以上参数 叫:元函数对象/仿函数

注意:

1.函数对象(仿函数)是一个类,不是一个函数。

2.函数对象(仿函数)重裁了"()"操作符使得它可以像函数一样调用。(仿函数概念由来)

 二、谓词

        返回值为bool类型普通函数或仿函数 都叫谓词。

如果谓词 有一个参数 叫:一元谓词

如果谓词 有二个参数 叫:二元谓词

一般没有多元谓词

1、一元谓词 

 用于查找:(头文件algorithm提供find_if算法策略)

 2、二元谓词

用于排序: (头文件algorithm提供sort算法策略)

#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool myGreater(int n1,int n2)
{return n1>n2;
}
class MyGreater
{
public:bool operator()(int n1,int n2){return n1>n2;}
};
void printVectorInt(vector<int> v)
{vector<int>::iterator it;for(it=v.begin();it!=v.end();it++){cout<<*it<<" ";}cout<<endl;
}void test()
{//sort排序vector<int> v;v.push_back(3);v.push_back(1);v.push_back(5);v.push_back(2);v.push_back(4);printVectorInt(v);sort(v.begin(),v.end());//顺序printVectorInt(v);//倒序//sort(v.begin(),v.end(),myGreater);sort(v.begin(),v.end(),MyGreater());printVectorInt(v);}int main(int argc, char *argv[])
{test();return 0;
}

关键代码及运行结果: 

三、内建函数对象 

        定义:系统提供好的 函数对象。(实质是类模板)

6个算数类函数对象,除了negate是一元运算,其他都是二元运算:

  • template<class T> T plus<T>//加法仿函数
  • template<class T> T minus<T>//减法仿函数
  • template<class T> T multiplies<T>//乘法仿函数
  • template<class T> T divides<T>//除法仿函数
  • template<class T> T modulus<T>//取模仿函数
  • template<class T> T negate<T>//取反仿函数

6个关系运算类函数对象,每一种都是二元运算:

  • template<class T> bool equal_to<T>//等于
  • template<class T> bool not_equal_to<T>//不等于
  • template<class T> bool greater<T>//大于
  • template<class T> bool greater_equal<T>//大于等于
  • template<class T> bool less<T>//小于
  • template<class T> bool less_equal<T>//小于等于

逻辑运算类运算函数,not为一元运算,其余为二元运算:

  • template<class T> bool logical_and<T>//逻辑与
  • template<class T> bool logical_or<T>//逻辑或
  • template<class T> bool logical_not<T>//逻辑非

一元谓词查找用内建函数实现:

 将二元谓词排序用内建函数对象实现:

 四、适配器

        适配器 为算法 提供接口。

1、函数对象 适配器

2、函数指针适配器 ptr_fun

3、成员函数 作为适配器 mem_fun_ref 

4、取反适配器 

not1函数:一元取反 

 not2函数: 二元取反

五、 常见算法

        头文件:#include<algorithm>,适用于随机访问迭代器。

1、遍历算法

(1)for_each遍历算法

        遍历容器元素:for_each(iterator beg, iterator end, _callback);

param beg 开始迭代器

param end 结束迭代器

param _callback 函数回调或者函数对象

return 函数对象

(2)transform算法

将指定容器区间元素搬运到另一容器中:

transform(iterator beg1, iterator end1, iterator beg2, _callbakc); 

注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存

param beg1 源容器开始迭代器

param end1 源容器结束迭代器

param beg2 目标容器开始迭代器

param _cakkback 回调函数或者函数对象

return 返回目标容器迭代器

2、查找算法

(1)find算法

查找元素:find(iterator beg, iterator end, value)

param beg 容器开始迭代器

param end 容器结束迭代器

param value 查找的元素

return 返回查找元素的位置

查找基本类型数据:

 查找自定义类型数据:

#include <iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class Person
{friend void test();
private:int num;string name;
public:Person(){}Person(int num,string name){this->num=num;this->name=name;}//重载==提供比较策略bool operator==(const Person &ob){return ((ob.name==this->name)&&(ob.num==this->num));}
};void test()
{vector<Person> v;v.push_back(Person(3,"tom"));v.push_back(Person(1,"bob"));v.push_back(Person(5,"张三"));v.push_back(Person(2,"小明"));v.push_back(Person(1,"小红"));vector<Person>::iterator ret;//find 查找自定义数据类型 需要重载==ret=find(v.begin(),v.end(),Person(5,"张三"));if(ret!=v.end()){cout<<"找到元素:"<<(*ret).num<<" "<<(*ret).name<<endl;}
}int main(int argc, char *argv[])
{test();return 0;
}

主函数代码及运行结果: 

(2)find_if算法 条件查找 

find_if(iterator beg, iterator end, _callback);

param beg 容器开始迭代器

param end 容器结束迭代器

param callback 回调函数或者谓词(返回bool类型的函数对象)

return bool 查找返回true 否则false

(3)adjacent_find算法 查找相邻重复元素 

        adjacent_find(iterator beg, iterator end, _callback);

param beg 容器开始迭代器

param end 容器结束迭代器

param _callback 回调函数或者谓词(返回bool类型的函数对象)

return 返回相邻元素的第一个位置的迭代器 

(4)binary_search算法 二分查找法

 bool binary_search(iterator beg, iterator end, value);

注意: 必须在有序序列中使用,在无序序列中不可用。

param beg 容器开始迭代器

param end 容器结束迭代器

param value 查找的元素

return bool 查找返回true 否则false

(5)count算法 统计元素出现次数

count(iterator beg, iterator end, value);

param beg 容器开始迭代器

param end 容器结束迭代器

param value  要统计的元素

return int返回元素个数

(6)count_if算法 按条件统计元素出现次数 

param beg 容器开始迭代器

param end 容器结束迭代器

param callback 回调函数或者谓词(返回bool类型的函数对象)

return int返回元素个数

 3、排序算法

(1)merge算法 容器元素合并

        merge算法 容器元素合并,并存储到另一容器中:

        merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterat or dest)

        注意:两个容器必须是有序的,合并后的容器仍然有序,目标容器需预留空间。

param beg1 容器1开始迭代器

param end1 容器1结束迭代器

param beg2 容器2开始迭代器

param end2 容器2结束迭代器

param dest 目标容器开始迭代器

(2)sort算法 容器元素排序

sort算法 容器元素排序 :sort(iterator beg, iterator end, _callback)

param beg 容器1开始迭代器

param end 容器1结束迭代器

param _callback 回调函数或者谓词(返回bool类型的函数对象) 

 (3)random_shuffle算法 对指定范围内的元素随机调整次序

        random_shuffle(iterator beg, iterator end)

param beg 容器开始迭代器

param end 容器结束迭代器

(4)reverse算法 反转指定范围的元素

        reverse(iterator beg, iterator end) 

param beg 容器开始迭代器 

param end 容器结束迭代器

4、拷贝替换算法

(1)copy算法 

copy算法 将容器内指定范围的元素拷贝到另一容器中 

copy(iterator beg, iterator end, iterator dest)

param beg 容器开始迭代器

param end 容器结束迭代器

param dest 目标起始迭代器

 copy提升:

(2)replace算法

        将容器内指定范围的旧元素修改为新元素:

        replace(iterator beg, iterator end, oldvalue, newvalue) 

param beg 容器开始迭代器

param end 容器结束迭代器

param oldvalue 旧元素

param oldvalue 新元素 

(3)replace_if算法

        replace_if算法 将容器内指定范围满足条件的元素替换为新元素 

        replace_if(iterator beg, iterator end, _callback, newvalue)

param beg 容器开始迭代器

param end 容器结束迭代器

param callback函数回调或者谓词(返回Bool类型的函数对象)

param oldvalue 新元素

(4)swap算法 互换两个容器的元素

        swap(container c1, container c2) 

param c1容器

param c2容器2

5、算数生成算法 

(1)accumulate算法 计算容器元素累计总和

        accumulate(iterator beg, iterator end, value)

param beg 容器开始迭代器

param end 容器结束迭代器

param value追加值 (求和完后 + value)

(2)fill算法 向容器中填满元素

        fill(iterator beg, iterator end, value)

param beg 容器开始迭代器

param end 容器结束迭代器

param value 填充元素

6、 集合算法

 (3)set_intersection求两个set集合的交集

set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)

注意:两个集合必须是有序序列

param beg1 容器1开始迭代器

param end1 容器1结束迭代器

param beg2 容器2开始迭代器

param end2 容器2结束迭代器

param dest 目标容器开始迭代器

return 目标容器的最后元素下一位置的迭代器地址

(2)set_union算法 求两个set集合的并集

set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)

注意:两个集合必须是有序序列

param beg1 容器1开始迭代器

param end1 容器1结束迭代器

param beg2 容器2开始迭代器

param end2 容器2结束迭代器

param dest 目标容器开始迭代器

return 目标容器的最后元素下一位置的迭代器地址

(3)set_difference算法 求两个set集合的差集

set_difference(iterator beg1, iterator end1, iterator beg2, iterator end 2, iterator dest) 

注意:两个集合必须是有序序列

param beg1 容器1开始迭代器

param end1 容器1结束迭代器

param beg2 容器2开始迭代器

param end2 容器2结束迭代器

param dest 目标容器开始迭代器

return 目标容器的最后一个元素的迭代器地址

六、综合案例

某市举行一场演讲比赛,共有24个人参加。比赛共三轮,前两轮为淘汰赛,第三轮为决 赛。

比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛;

  • 第一轮分为4个小组,每组6个人。比如编号为: 100-123. 整体进行抽签 (draw)后顺序演讲。当小组演讲完后,淘汰组内排名最后的三个选手,然后 继续下一个小组的比赛。
  • 第二轮分为2个小组,每组6人。比赛完毕,淘汰组内排名最后的三个选手,然后继续下一 个小组的比赛。
  • 第三轮只剩下1组6个人,本轮为决赛,选出前三名。

比赛评分:10个评委打分,去除最 低、最高分,求平均分每个选手演讲完由10个评委分别打分。该选手的最终得分是去掉一 个最高分和一个最低分,求得剩下的8个成绩的平均分。选手的名次按得分降序排列。

需求分析: 1) 产生选手 ( ABCDEFGHIJKLMNOPQRSTUVWX ) 姓名、得分;选手编 号

实现思路:需要把选手信息、选手得分信息、选手比赛抽签信息、选手的晋级信息保存在容器中,需要涉及到各个容器的选型。选手可以设计一个类Speaker(姓名和得分)所有选手的编号可以单独放在一个vector容器中,做抽签用-所有选手编号和选手信息,可以放在map容器内。

#include <iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<stdlib.h>
#include<time.h>
#include<deque>
using namespace std;
class player
{friend void play(int index,vector<int> &v, map<int,player> &m, vector<int> &v1);
private:int num;string name;float score[3];
public:player(){}player(int num,string name){this->name=name;this->num=num;}
};
void createPlayer(vector<int> &v,map<int,player> &m)
{string seedname="ABCDEFGHIJKLMNOPQRSTUVWX";for(int i=0;i<24;i++){string tmpname="选手";tmpname+=seedname[i];int num=i;v.push_back(num);m.insert(make_pair(num,player(num,tmpname)));}
}
void play(int index,vector<int> &v,map<int,player> &m,vector<int> &v1)
{//选手编号随机分组srand(time(NULL));random_shuffle(v.begin(),v.end());multimap<float,int,greater<float>> mul;//存放每组的分数‐‐编号vector<int>::iterator it=v.begin();int count=0;cout<<"-------第"<<index<<"轮比赛-------"<<endl;//每名选手比赛for(;it!=v.end();it++){count++;//定义deque容器 存放评委打分deque<float> d;int i=0;for(;i<10;i++){d.push_back((float)(rand()%41+60));}//排序sort(d.begin(),d.end());//去掉最高、最低分d.pop_front();d.pop_back();//求平均分float avg=accumulate(d.begin(),d.end(),0)/d.size();//将平均分 赋值给m中选手m[*it].score[index-1]=avg;mul.insert(make_pair(avg, *it));if(count%6==0)//刚好一组{cout<<"\t第"<<count/6<<"组的晋级名单:"<<endl;int i=0;multimap<float,int,greater<float>>::iterator mit=mul.begin();for(;i<3;i++,mit++){v1.push_back( (*mit).second);cout<<"\t\t"<<(*mit).second<<" "<<(*mit).first<<endl;}cout<<"\t第"<<count/6<<"组的得分情况:"<<endl;mit=mul.begin();for(int i=0;i<6;i++,mit++){int num=(*mit).second;cout<<"\t\t"<<num<<" "<<m[num].name<<" "<<m[num].score[index-1]<<endl;}mul.clear();}}
}void test()
{vector<int> v;map<int,player> m;//创建选手createPlayer(v,m);vector<int> v1;//存放晋级选手的编号play(1,v,m,v1);vector<int> v2;//存放晋级选手的编号play(2,v1,m,v2);vector<int> v3;//存放晋级选手的编号play(3,v2,m,v3);
}int main(int argc, char *argv[])
{test();return 0;
}

运行结果:


 

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

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

相关文章

K8S存储卷与PV,PVC

一、前言 Kubernetes&#xff08;K8s&#xff09;中的存储卷是用于在容器之间共享数据的一种机制。存储卷可以在多个Pod之间共享数据&#xff0c;并且可以保持数据的持久性&#xff0c;即使Pod被重新调度或者删除&#xff0c;数据也不会丢失。 Kubernetes支持多种类型的存储卷…

Three.js-03Vite打包入门

1.安装 说明&#xff1a;创建文件以后&#xff0c;按照提示进行操作。如cd文件夹&#xff0c;npm i ,npm run dev等操作。 npm create vitelatest 2.安装three npm i three.js 4.打开npm官网 说明:搜索three第三方库。按照案例进行操作。 5.修改App.vue文件 <script set…

手撕LRU缓存——LinkedHashMap简易源码

题目链接&#xff1a;https://leetcode.cn/problems/lru-cache/description/?envTypestudy-plan-v2&envIdtop-100-liked 原理非常简单&#xff0c;一个双端链表配上一个hash表。 首先我们要知道什么是LRU就是最小使用淘汰。怎么淘汰&#xff0c;链表尾部就是最不常用的直接…

Google大模型Bard更名Gemini,现在实力如何?(VS gpt系列)

名人说&#xff1a;一花独放不是春&#xff0c;百花齐放花满园。——《增广贤文》 作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、简要介绍1、Gemini是什么&#xff1f;2、主要特点3、Gemini的版本4、应用潜力5、…

zookeeper启动报错

启动zookeeper报错 从报错中可以看到 Invalid config, exiting abnormally 意思是&#xff1a;配置无效&#xff0c;异常退出 在往上看是没有zoo.cof这个配置文件 2024-02-27 14:47:03,285 [myid:] - ERROR [main:o.a.z.s.q.QuorumPeerMain99] - Invalid config, exiting…

基于AMDGPU-ROCm的深度学习环境搭建

在风起云涌的AI江湖&#xff0c;NVIDIA凭借其CUDA生态和优秀的硬件大杀四方&#xff0c;立下赫赫战功&#xff0c;而另一家公司AMD也不甘示弱&#xff0c;带着他的生态解决方案ROCm开始了与不世出的NVIDA的正面硬钢&#xff0c;"ROCm is the answer to CUDA", AMD官网…

Java——数组的定义与使用

目录 一.数组的基本概念 1.什么是数组 2.数组的创建及初始化 3.数组的使用 二.数组是引用类型 1.初始JVM的内存分布 2.基本类型变量与引用类型变量的区别 3.再谈引用变量 4.认识 null 三.数组的应用场景 1.保存数据 2.作为函数的参数 2.1参数传基本数据类型 2.…

学习vue3第二节(使用vite 创建vue3项目)

使用vite 创建vue3项目 node 安装请移步 node官网&#xff1a; https://nodejs.p2hp.com/ node 版本控制 请移步 nvm官网&#xff1a;https://nvm.uihtm.com/ vite 生成vue项目完整版 请移步 vite官网&#xff1a;https://cn.vitejs.dev/ 1、使用 npm 或者 yarn 创建vue3 项目…

NXP实战笔记(十一):32K3xx基于RTD-SDK在S32DS上配置DFLASH、MemAcc、Fee

目录 1、概述 2、RTD-SDK配置之Cache_Ip 3、RTD-SDK配置之Mem_43_InFls 4、RTD-SDK配置之MemAcc 5、RTD-SDK配置之Fee 6、代码示例 1、概述 S32K3目前安装的RTD普遍使用的是R22-11版本的AUTOSAR规范&#xff0c;作为一直使用AUTOSAR4.2.2的程序员来讲&#xff0c;属实迭代…

东方博宜 1511. 数字之和为13的整数

东方博宜 1511. 数字之和为13的整数 #include<iostream> using namespace std; int main() {int n ;cin >> n ;int cnt 0 ;for(int i 1 ; i < n ; i){int sum 0 ;int y ;y i ;while(true){sum y%10;y y / 10 ;if(y0)break; }if(sum 13)cnt 1 ; }cout…

91、在推理流程中加载动态库中的Infer函数

注:建议在 new_version_with_notes 目录下尝试本节内容,有更为丰富的细节输出。 在上一节将生成的代码编译成一个动态链接库之后,接下来需要加载动态链接库中写好的推理入口函数,完成推理。 在生成的代码中,在 codegen 目录下,有一个 codegen.cc 文件,里面是一个 Infe…

二、TensorFlow结构分析(2)

目录 1、会话 1.1 __init__(target,graphNone,configNone) 1.2 会话的run() 1.3 feed操作 TF数据流图图与TensorBoard会话张量变量OP高级API 1、会话 1.1 __init__(target,graphNone,configNone) def session_demo():# 会话的演示# Tensorflow实现加法运算a_t tf.constan…

Appium + mitmProxy 实现APP接口稳定性测试

随着 App 用户量的不断增长&#xff0c;任何小的问题都可能放大成严重的线上事故&#xff0c;为了避免对App造成损害的任何可能性&#xff0c;我们必须从各个方面去思考 App 的稳定性建设&#xff0c;尽可能减少任何潜在的威胁。 1.背景介绍 为了保障 App 的稳定性&#xff0…

算法基础(三)(模拟)

1.模拟算法介绍&#xff1a; 模拟算法通过模拟实际情况来解决问题&#xff0c;一般容易理解但是实现起来比较复杂&#xff0c;有很多需要注意的细节&#xff0c;或者是一些所谓很“麻烦”的东西。模拟题一般不涉及太难的算法&#xff0c;一般就是由较多的简单但是不好处理的部…

redis启动错误

错误&#xff1a; Creating Server TCP listening socket 127.0.0.1:6379: bind: No error redis-server.exe redis.windows.conf redis-cli.exe shutdown auth "yourpassword"

9 easy 28. 找出字符串中第一个匹配项的下标

暴力法&#xff1a; //给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。 //如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 // // // // 示例 1&…

harbor配置目录被误删后救援

我司微服务产品的业务镜像&#xff0c;在客户现场上云安全检测中发现需要打补丁&#xff1b;放在角落、时不常用一次的harbor镜像仓库需要用到了&#xff1a;将加固后的基础镜像上传以备份&#xff0c;方便其他同学拉取使用。 然鹅&#xff0c;启动后harbor-db频繁重启 harbo…

最新 CLion 2023.3.4 下载与安装 + 永久免费

文章目录 Stage 1 : 官网下载Stage 2 : 下载工具Stage 3-1 : windows为例Stage 3-2 : mac为例常见问题部分小伙伴 Mac 系统执行脚本遇到如下错误&#xff1a;解决方法&#xff1a; 执行脚本做了啥&#xff1f;和正版区别&#xff1f; Stage 1 : 官网下载 先去官网下载 我这里下…

EAP-TLS实验之H3C MSR2600-10-X1配置相关

H3C MSR2600充当802.1x流程中的NAS&#xff08;Network Access System&#xff09;角色&#xff0c;一般负责实际待验证的设备与认证服务器之间沟通的桥梁&#xff08;当然也可以配置成认证服务器角色&#xff09;工作。在挑选购买支持802.1x的路由器或交换机时需要跟厂家明确是…

DFS之剪枝与优化

剪枝 1.优化搜索顺序&#xff1a;在大部分情况下&#xff0c;我们应该优先搜索分支较少的结点 2.排除等效冗余&#xff08;在不考虑顺序的情况下&#xff0c;尽量用组合的方式来搜索&#xff09; 3.可行性剪枝 4.最优性剪枝 5.记忆化搜索 165. 小猫爬山 - AcWing题库 import …