疯子的算法总结(二) STL Ⅰ 算法 ( algorithm )
写在前面:
为了能够使后续的代码具有高效简洁的特点,在这里讲一下STL,就不用自己写堆,写队列,但是做为ACMer不用学的很全面,我认为够用就好,我只写我用的比较多的。
什么是STL(STl内容):
容器(Container):
是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器;
迭代器(Iterator):
提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定了operator*()以及其他类似于指针的操作符地方法的类对象;
算法(Algorithm):
是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;
仿函数(Functor)
适配器(Adaptor)
分配器(allocator)
仿函数、适配器、与分配器用的比较少,甚至没用过!在这里不做说明,有兴趣可以自己学习一下,那个东西C++软件工程可能用的比较多。
一、算法 ( algorithm )
如果有不理解的容器知识可以先去看看容器
<一>查找算法(9个):判断容器中是否包含某个值
(可以去看看C++primer学学别的,但是我认为太多了没必要)
1.count:
利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[14]={0,1,2,3,4,5,6,7,7,7,7,7,7,8};
cout<<count(a,a+14,7)<<endl;
vector<int> demo;
for(int i=0;i<10;i++)
demo.push_back(i);
demo.push_back(1);
cout<<count(demo.begin(),demo.end(),1)<<endl;
}
//运行结果 6 2;
2.count_if:
利用输入的操作符,对标志范围内的元素进行操作,返回结果为true的个数。
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a)
{
return (a>1);
}
int main()
{
int a[14]={0,1,2,3,4,5,6,7,7,7,7,7,7,8};
int po=count_if(a,a+14,cmp);
cout<<po<<endl;
vector<int> demo;
for(int i=0;i<10;i++)
demo.push_back(i);
demo.push_back(1);
int poi=count_if(demo.begin(),demo.end(),cmp);
cout<<poi<<endl;
}// 运行结果 8 12
//看到网上大佬的代码写的比较深奥,特地去查了查书,我这样用没毛病的。
补充:捕获值列表,是允许我们在Lambda表达式的函数体中直接使用这些值,捕获值列表能捕获的值是所有在此作用域可以访问的值,包括这个作用域里面的临时变量,类的可访问成员,全局变量。捕获值的方式分两种,一种是按值捕获,一种是按引用捕获。顾名思义,按值捕获是不改变原有变量的值,按引用捕获是可以在Lambda表达式中改变原有变量的值。
[捕获值列表]:
1、空。没有使用任何函数对象参数。
2、=。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
3、&。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
4、this。函数体内可以使用Lambda所在类中的成员变量。
5、a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
6、&a。将a按引用进行传递。
7、a, &b。将a按值进行传递,b按引用进行传递。
8、=,&a,&b。除a和b按引用进行传递外,其他参数都按值进行传递。
9、&, a, b。除a和b按值进行传递外,其他参数都按引用进行传递。
3.equal_range:
功能类似equal,返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a)
{
return (a>1);
}
int main()
{
// int a[14]= {0,1,2,3,4,5,6,7,7,7,7,7,7,8};
//equal_range(a,a+14,auto po);
vector<int> demo;
for(int i=0; i<10; i++) demo.push_back(i);
demo.push_back(1);
cout<<*equal_range(demo.begin(),demo.end(),7).first<<endl;
cout<<*equal_range(demo.begin(),demo.end(),7).second<<endl;
cout<<equal_range(demo.begin(),demo.end(),7).first-demo.begin()<<endl;
cout<<equal_range(demo.begin(),demo.end(),7).second-equal_range(demo.begin(),demo.end(),7).first<<endl;
}
//也可以加cmp函数,同样适用于数组,在下文中不再举出数组的例子
4.find:
利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的一个InputIterator。
补充
InputIterator是用于输入的Iterator
OutputIterator是用于输出的Iterator
ForwardIterator是InputIterator,同时可以保证++运算不会使之失效
RandomIterator是ForwardIterator,同时具有+,-,+=,-=等运算及各种比较操作
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[14]= {0,1,2,3,4,5,6,7,7,7,7,7,7,8};
vector<int> demo;
for(int i=0; i<14; i++) demo.push_back(a[i]);
demo.push_back(1);
cout<<find(demo.begin(),demo.end(),8)-demo.begin()<<endl;
} //可以直接取地址获取值。
5.find_end:
在指定范围内查找"由输入的另外一对iterator标志的第二个序列"的最后一次出现。找到则返回最后一对的第一个ForwardIterator,否则返回输入的"另外一对"的第一个ForwardIterator。重载版本使用用户输入的操作符代替等于操作。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[14]= {0,1,2,3,4,5,6,7,7,7,7,7,7,8};
vector<int> demo;
for(int i=0; i<14; i++) demo.push_back(a[i]);
demo.push_back(1);
cout<<find_end(demo.begin(),demo.end(),a+2,a+3)-demo.begin()<<endl;
}
6.find_first_of:
在指定范围内查找"由输入的另外一对iterator标志的第二个序列"中任意一个元素的第一次出现。重载版本中使用了用户自定义操作符。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[14]= {0,1,2,3,4,5,6,7,7,7,7,7,7,8};
vector<int> demo;
for(int i=0; i<14; i++) demo.push_back(a[i]);
demo.push_back(1);
cout<<find_first_of(demo.begin(),demo.end(),a+2,a+3)-demo.begin()<<endl;
}
7.find_if:
使用输入的函数代替等于操作符执行find。返回的是迭代器,为了是大家更明白的理解,减去第一个元素的位置,就相当于得到了下标;
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int w) {
return w>5;
}
int main()
{
int a[14]= {0,1,2,3,4,5,6,7,7,7,7,7,7,8};
vector<int> demo;
for(int i=0; i<14; i++) demo.push_back(a[i]);
cout<< find_if(demo.begin(),demo.end(),cmp)-demo.begin();
}
8.lower_bound:
返回一个ForwardIterator,指向在有序序列范围内的可以插入指定值而不破坏容器顺序的第一个位置。重载函 数使用自定义比较操作。
在一个有序的范围内时间复杂度为log2n,普遍适用于二分算法。
跟3.equal_range的用法一样不过这个返回的是first
9.upper_bound:
返回一个ForwardIterator,指向在有序序列范围内插入value而不破坏容器顺序的最后一个位置,该位置标志 一个大于value的值。重载函数使用自定义比较操作。跟3.equal_range的用法一样不过这个返回的是second;
<二>排序和通用算法(7个):提供元素排序策略
inplace_merge:
合并两个有序序列,结果序列覆盖两端范围。重载版本使用输入的操作进行排序。
merge:
合并两个有序序列,存放到另一个序列。重载版本使用自定义的比较。 nth_element:
将范围内的序列重新排序,使所有小于第n个元素的元素都出现在它前面,而大于它的都出现在后面。重载版本使用自定义的比较操作。partial_sort:
对序列做部分排序,被排序元素个数正好可以被放到范围内。重载版本使用自定义的比较操作。
partial_sort_copy:
与partial_sort类似,不过将经过排序的序列复制到另一个容器。 partition:
对指定范围内元素重新排序,使用输入的函数,把结果为true的元素放在结果为false的元素之前。 random_shuffle:
对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作。 reverse:
将指定范围内元素重新反序排序。 reverse_copy: 与reverse类似,不过将结果写入另一个容器。rotate:
将指定范围内元素移到容器末尾,由middle指向的元素成为容器第一个元素。
rotate_copy:
与rotate类似,不过将结果写入另一个容器。
sort:(常用,相信大家都不陌生)
以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作。
sort(首地址,第一个不合法地址(即末地址+1),cmp)//cmp可以缺省
bool cmp()//可以用到结构体上
{
return ();
}
stable_sort:
与sort类似,不过保留相等元素之间的顺序关系。 stable_partition:
与partition类似,不过不保证保留容器中的相对顺序。 <三>删除和替换算法(15个) copy:
复制序列 copy_backward: 与copy相同,不过元素是以相反顺序被拷贝。 iter_swap:
交换两个ForwardIterator的值。
<三>删除修改复制(12个):简单操作区间元素
remove:
删除指定范围内所有等于指定元素的元素。注意,该函数不是真正删除函数。内置函数不适合使用remove和 remove_if函数。
remove_copy:
将所有不匹配元素复制到一个制定容器,返回OutputIterator指向被拷贝的末元素的下一个位置。remove_if:
删除指定范围内输入操作结果为true的所有元素。
remove_copy_if:
将所有不匹配元素拷贝到一个指定容器。
replace:
将指定范围内所有等于vold的元素都用vnew代替。
replace_copy:
与replace类似,不过将结果写入另一个容器。
replace_if:
将指定范围内所有操作结果为true的元素用新值代替。
replace_copy_if:
与replace_if,不过将结果写入另一个容器。
swap:
交换存储在两个对象中的值。
swap_range:
将指定范围内的元素与另一个序列元素值进行交换。
unique: (常用于离散化)
清除序列中重复元素,和remove类似,它也不能真正删除元素。重载版本使用自定义比较操作。
unique_copy: (同上)
与unique类似,不过把结果输出到另一个容器。
<四>排列组合算法(2个):提供计算给定集合按一定顺序的所有可能排列组合
以深搜的形式实现:
next_permutation:
取出当前范围内的排列,并重新排序为下一个排列。重载版本使用自定义的比较操作。
prev_permutation:
取出指定范围内的序列并将它重新排序为上一个序列。如果不存在上一个序列则返回false。重载版本使用 自定义的比较操作。
//常以此方式使用,但时间复杂度N!这个。。。。
do
{
//操作
}while((next_permutation(首地址,第一个不合法地址)
<五>生成和异变算法(3个)
fill:
将输入值赋给标志范围内的所有元素。fill(首地址,第一个不合法地址,2); //该区间内全部赋值为2
区别于memset,memset是按位赋值,只能赋每位值相同值。
memset(首地址,value,(字节数)常用sizeof()获取)
fill_n:
将输入值赋给first到first+n范围内的所有元素。
// 从开始以此赋值,3个5
fill_n(首地址,3,5);
transform:
将输入的操作作用与指定范围内的每个元素,并产生一个新的序列。重载版本将操作作用在一对元素上,另外一个元素来自输入的另外一个序列。结果输出到指定容器。
transform (原始对象首地址, 原始对象第一个不合法地址, 输出对象首地址, operate(操作函数));
char operate(char c)//常用转化大小写,以此为例子
{
if (isupper(c))
{
return c+32;
}
return c;
}
<六>关系算法(6个)
equal:
如果两个序列在标志范围内元素都相等,返回true。重载版本使用输入的操作符代替默认的等于操作符。
includes:
判断第一个指定范围内的所有元素是否都被第二个范围包含,使用底层元素的<操作符,成功返回true。重载版本使用用户输入的函数。
max:(很多人问我,这不是cmath吗,呃。。。。。不是)
返回两个元素中较大一个。重载版本使用自定义比较操作。max(3,5)的值是5;
max_element:
返回一个ForwardIterator,指出序列中最大的元素。重载版本使用自定义比较操作。
max_element(a, a+6) 返回一个最大值位置指针
min:
返回两个元素中较小一个。重载版本使用自定义比较操作。
min(3,5)的值是5;
min_element:
返回一个ForwardIterator,指出序列中最小的元素。重载版本使用自定义比较操作。
<七>集合算法(4个)
set_union:
构造一个有序序列,包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作。set_intersection:
构造一个有序序列,其中元素在两个序列中都存在。重载版本使用自定义的比较操作。set_difference:
构造一个有序序列,该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用自定义的比较操作。set_symmetric_difference:
构造一个有序序列,该序列取两个序列的对称差集(并集-交集)。
<八>堆算法(4个)
make_heap:
把指定范围内的元素生成一个堆。重载版本使用自定义比较操作。
pop_heap:
并不真正把最大元素从堆中弹出,而是重新排序堆。它把first和last-1交换,然后重新生成一个堆。可使用容器的back来访问被"弹出"的元素或者使用pop_back进行真正的删除。重载版本使用自定义的比较操作。
push_heap:
假设first到last-1是一个有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。在指向该函数前,必须先把元素插入容器后。重载版本使用指定的比较操作。
sort_heap:
对指定范围内的序列重新排序,它假设该序列是个有序堆。重载版本使用自定义比较操作。
疯子的算法总结(二) STL Ⅰ 算法 ( algorithm )的更多相关文章
- 最短路径算法之二——Dijkstra算法
Dijkstra算法 Dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 注意该算法要求图中不存在负权边. 首先我们来定义一个二维数组Edge[MAXN][MAXN]来存储 ...
- 个性化召回算法实践(二)——LFM算法
LFM算法核心思想是通过隐含特征(latent factor)联系用户兴趣和物品,找出潜在的主题和分类.LFM(latent factor model)通过如下公式计算用户u对物品i的兴趣: \[ P ...
- 个性化排序算法实践(二)——FFM算法
场感知分解机(Field-aware Factorization Machine ,简称FFM)在FM的基础上进一步改进,在模型中引入类别的概念,即field.将同一个field的特征单独进行one- ...
- 【STL源码学习】STL算法学习之二
第一章:前言 学习笔记,记录学习STL算法的一些个人所得,在以后想用的时候可以快速拾起. 第二章:明细 copy 函数原型: template <class InputIterator, cla ...
- 数据结构看书笔记(二)--算法(Algorithm)简介
算法:是解决问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作. 算法的特性:算法具有五个特性:输入.输出.有穷性.确定性.可行性 输入输出:算法具有零个或多个输入:至 ...
- STL算法
STL算法部分主要由头文 件<algorithm>,<numeric>,<functional>组成.要使用 STL中的算法函数必须包含头文件<algorit ...
- STL源代码分析——STL算法remove删除算法
前言 因为在前文的<STL算法剖析>中,源代码剖析许多.不方便学习,也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的remove删除算法. ...
- STL源代码分析——STL算法merge合并算法
前言 因为在前文的<STL算法剖析>中.源代码剖析许多.不方便学习.也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的merge合并算法. ...
- STL源代码分析——STL算法sort排序算法
前言 因为在前文的<STL算法剖析>中,源代码剖析许多,不方便学习,也不方便以后复习.这里把这些算法进行归类,对他们单独的源代码剖析进行解说.本文介绍的STL算法中的sort排序算法,SG ...
- C++11 STL算法简介
STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库.它被容纳于C++标准程序库(C++ Standard Library)中,是ANS ...
随机推荐
- 基于STM32之UART串口通信协议(一)详解
一.前言 1.简介 写的这篇博客,是为了简单讲解一下UART通信协议,以及UART能够实现的一些功能,还有有关使用STM32CubeMX来配置芯片的一些操作,在后面我会以我使用的STM32F429开发 ...
- c语言:链表
1.链表概述: 链表是一种数据结构,它采用动态分配存储单元方式.它能够有效地节省存储空间(同数组比较). 由于链表中的节点是一个结构体类型,并且结点中有一个成员用于指向下一个结点.所以定义作为结点的格 ...
- HDU XXXX:求[L,R]的素数数量(数位DP)
Problem G Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/131072K (Java/Other) Total S ...
- Ng-Matero:基于 Angular Material 搭建的中后台管理框架
前言 目前市面上关于 Angular Material 的后台框架比较少,大多都是收费主题,而且都不太好用. 很多人都说 Material 是一个面向 C 端的框架,其实在使用其它框架做管理系统的时候 ...
- VM虚拟机 VMWare Workstation Pro v15.0.1 中文破解版
虚拟机软件VMware Workstation Pro 15.0 全新版本发布,此次更新了诸多客户机操作系统版本,另外完全兼容Win10创意者更新支持.12.0之后属于大型更新,专门为Win10的安装 ...
- Redis图形化客户端管理软件推荐
Redis是一个超精简的基于内存的键值对NOSQL数据库(key-value),一般对并发有一定要求的应用都用其储存session,乃至整个数据库.不过它公自带一个最小化的命令行式的数据库管理工具re ...
- SpringBoot 2.0.3 源码解析
前言 用SpringBoot也有很长一段时间了,一直是底层使用者,没有研究过其到底是怎么运行的,借此机会今天试着将源码读一下,在此记录...我这里使用的SpringBoot 版本是 2.0.3.RE ...
- Spring Boot微服务电商项目开发实战 --- 多环境部署配置、端口号统一配置及Dubbo提供者消费者实现
昨天已经搭建好了SpringBoot基于Maven的基础父子级项目,今天开始进入项目分模块及分布式实现.首先我们基于昨天的项目,在父级工程下建lyn-sys,lyn-customer,lyn-good ...
- [原创]MySQL数据库查询和LVM备份还原学习笔记记录
一.查询语句类型: 1)简单查询 2)多表查询 3)子查询 4)联合查询 1)简单查询: SELECT * FROM tb_name; SELECT field1,field2 FROM tb_nam ...
- java调用新浪接口根据Ip查询所属地区
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import ...