定义
STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中最新的也是极具革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。
STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但这种分离确实使得STL变得非常通用。例如,由于STL的sort()函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组;
STL另一个重要特性是它不是面向对象的。为了具有足够通用性,STL主要依赖于模板而不是封装,继承和虚函数(多态性)——OOP的三个要素。你在STL中找不到任何明显的类继承关系。这好像是一种倒退,但这正好是使得STL的组件具有广泛通用性的底层特征。另外,由于STL是基于模板,内联函数的使用使得生成的代码短小高效;
从逻辑层次来看,在STL中体现了泛型化程序设计的思想,引入了诸多新的名词,比如像需求(requirements),概念(concept),模型(model),容器(container),算法(algorithmn),迭代子(iterator)等。与OOP(object-oriented programming)中的多态(polymorphism)一样,泛型也是一种软件的复用技术;从实现层次看,整个STL是以一种类型参数化的方式实现的,这种方式基于一个在早先C++标准中没有出现的语言特性–模板(template)。
组件
1)容器(Container),是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器;
#include<iostream>
#include <numeric>
#include <algorithm>
#include <iterator>
#include<string>
#include<vector>
#include <array>
#include <deque>
#include <forward_list>
#include <list>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
using namespace std;
int main()
{
/*顺序容器*/
//共同方法
std::vector<int> con;
//得到首尾迭代器,返回类型为iterator
con.begin(), con.end();
//得到首尾常量迭代器,返回类型为const_iterator
con.cbegin(),con.cend();
//得到首尾逆迭代器,返回类型为reverse_iterator, forward_list没有该方法
con.rbegin(), con.rend();
//得到容器内元素个数,forward_list没有该方法
con.size();
//清空容器,array没有该方法
con.clear();
//1:array - 与数组类似,但更安全,并且可以使用标准算法
//包含头文件 #include <array>
//创建一个固定大小的array,跟数组类似,这个大小不可改变
array<int, 5> ary;
//[]或at访问对应位置的元素,at比[]安全,因为at进行下标检查
ary[0] = ary.at(0);
for (int i = 0; i < ary.size(); ++i)
{
// cout<< "数组的逐个元素" << ary[i] << "\n";
}
//2:vector - 向量,动态数组,可自动扩充容量。随机访问快,除尾部之外的增减慢。
//包含头文件 #include <vector>
//创建一个可容纳int的vector,其他类型类似
vector<int> vec;
//末尾添加一个元素
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
//从末尾删去一个元素
// vec.pop_back();
//在指定位置插入一个元素, 第一个元素为vector<int>::const_iterator类型
//insert采用拷贝的方式添加元素,emplace则采用直接构造的方式添加元素
vec.insert(vec.cbegin(), 2);
// vec.emplace(vec.cbegin(), 0);
//删去指定位置的元素,参数为vector<int>::const_iterator类型
vec.erase(vec.cbegin());
//使用下标或者使用at访问对应位置的元素
// vec[0] = vec.at(0);
for (int i = 0; i < vec.size(); ++i)
{
// cout<< "向量的逐个元素" << vec[i] << "\n";
}
//2.1二维向量
vector<pair<int, int>> vec2;
for(int i = 0; i < 10; i++){
vec2.emplace_back(make_pair(10-i,i));
}
for(int j=0; j<vec2.size(); j++){
cout << "二维向量" << vec2[j][0] << vec2[j][j] << endl;
}
//3:deque - 双向动态数组,可以看成vector的双向版本
//需要包含的头文件#include <deque>
//创建可容纳int元素的deque
deque<int> dq;
//头插和头删
dq.push_front(1), dq.pop_front();
//尾插和尾删
dq.push_back(2), dq.pop_back();
//在指定位置插入
dq.insert(dq.cbegin(), 1);
// dq.emplace(dq.cbegin(), 1);
//删除指定位置的元素
dq.erase(dq.cbegin());
//使用下标或at访问指定位置的元素
// dq[0] = dq.at(0);
for (int i = 0; i < dq.size(); ++i)
{
// cout<< "队列的逐个元素" << dq.at(i) << "\n";
}
//4:forward_list - 单向链表,唯一不提供size()方法,并且插入和删除都是在给定位置之后
//包含头文件#include <forward_list>
//创建可以容纳int元素的forward_list
forward_list<int> fl;
//头插
fl.push_front(1);
fl.push_front(2);
fl.push_front(3);
fl.push_front(4);
fl.push_front(5);
fl.push_front(6);
fl.push_front(7);
fl.push_front(8);
fl.push_front(9);
fl.push_front(10);
//头删
// fl.pop_front();
//删除容器中所有等于val的元素
fl.remove(5);
//插入指定位置之后的元素,在这里,如果fl非空,则2成为第二个元素
fl.insert_after(fl.cbegin(), 2);
// fl.emplace_after(fl.cbegin(), 2);
//删除指定位置之后的元素,在这里,删除第二个元素
fl.erase_after(fl.cbegin());
int size = distance(fl.begin(),fl.end());
// cout << "单向链表的大小" << size << "\n";
forward_list<int>::iterator i;
for (i = fl.begin(); i != fl.end(); ++i){
// cout << "单向链表中逐个元素" << *i << "\n";
}
//5:list - 双向链表,支持双向插入删除,只支持顺讯访问,增删块
//需要包含头文件#include <list>
//创建一个容纳int的list
list<int> lst;
//头插或尾插
lst.push_front(1), lst.push_back(2);
lst.push_front(3), lst.push_back(4);
lst.push_front(5), lst.push_back(6);
//头删或尾删
lst.pop_front(), lst.pop_back();
//在指定位置插入
lst.insert(lst.cbegin(), 1);
// lst.emplace(lst.cbegin(), 1);
//在指定位置删除
lst.erase(lst.cbegin());
list<int>::iterator j;
for (j = lst.begin(); j != lst.end(); ++j){
cout << "链表中逐个元素" << *j << "\n";
}
//6:stack - 栈,先进后出,默认容器为deque,vector和list,并且不允许遍历
//包含的头文件#include <stack>
//创建一个能容纳int元素的stack
stack<int> s;
//将一个元素入栈
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
//返回栈顶元素
cout << "栈顶元素" << s.top() << "\n";
//将栈顶元素出栈
s.pop();
cout << "出栈后栈顶元素" << s.top() << "\n";
cout << "栈的大小" << s.size() << "\n";
cout << "栈是否为空" << s.empty() << "\n";
//7:queue - 队列,先进先出,默认容器为deque,vector和list,并且不允许遍历
//包含头文件#include <queue>
//创建可容纳int型元素的queue
queue<int> q;
//使一个元素入队
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
//使第一个元素出队
q.pop();
//返回队首元素
cout << "队首元素" << q.front() << "\n";
//返回队尾元素
cout << "队尾元素" << q.back() << "\n";
cout << "队列的大小" << q.size() << "\n";
cout << "队列是否为空" << q.empty() << "\n";
//8: priority_queue -优先队列,其底层是用堆来进行实现的,默认规则就是优先级最高的放在队首,优先级对它们的设置默认都是数字大的优先级越高,队首元素就是优先队列内元素最大的那个
/*定义:priority_queue<Type, Container, Functional>
Type 就是数据类型。(int ,double等.)
Container 就是容器类型(Container必须是用数组实现的容器,默认vector,但不能用 list。)
Functional 就是比较的方式(可以自定义,默认从小到大排序)
*/
// priority_queue<int, vector<int>, less<int> > p1 这样声明降序排序
// priority_queue<int, vector<int>, greater<int> > p1 这样声明升序排序
priority_queue<int> p1; // 默认为降序排序
p1.push(1);
p1.push(3);
p1.push(5);
p1.push(7);
p1.push(8);
p1.push(2);
//队列中的内容会自动排序: 8,7,5,3,2,1;
cout << "队头元素" << p1.top() << endl;
p1.pop();
cout << "队头元素" << p1.top() << endl;
p1.pop();
cout << "队头元素" << p1.top() << endl;
p1.pop();
cout << "队头元素" << p1.top() << endl;
p1.pop();
cout << "队头元素" << p1.top() << endl;
/*关联容器*/
//共有八种,分为两大类:map和set.他们的共同方法有begin(),end()和size()等
//1:map
//1.1 : map - 关联数组,保存键值对,数据存放是有序的
//1.2 : multimap - 关键字可重复出现的map。
//1.3 : unordered_map:使用hash函数的map,数据存放是无序的。
//1.4 : unordered_multimap:在unordered_map的基础上,关键字可重复出现。
//包含头文件
//map和multimap需包含<map>
// #include <map>
//unordered_map和unordered_multimap需包含<unordered_map>
// #include <unordered_map>
//创建一个key为string元素,value为int元素的map
map<string, int> m;
//向m中添加一个键值对,map的value_type为对应的pair,下列四种方式均可
m.insert(pair<string, int>("hello", 1));
m.insert(make_pair("hello", 1));
// m.emplace("hello", 1);
m["hello"] = 1;
//查看map中是否有指定的key,若没有,则返回尾后迭代器
m.find("hello");
//查看某个key所对应的value
//使用下标,如果没有key为"world"的键值对,则创建("world", 0)键值对并添加至这个map
m["world"];
//使用at,若没有该键值对,则报错
m.at("world");
//最好的访问方法为,先判断有没有该键值对,若有,再进行访问
if (m.find("world") != m.end())
cout << m["world"] << endl;
//删除key为“hello”的键值对,不管是否有该键值对,都不会报错
m.erase("hello");
//2:set
//2.1: set - 只保留关键字的容器(关键字即值)。
//2.2: multiset - 关键字可重复出现
//2.3: unordered_set - 无序的set
//2.4: unordered_multiset - 在unordered_set的基础上关键字可重复。
//需包含的头文件
//set和multiset需要包含<set>
// #include <set>
//unordered_set和unordered_multiset需要包含<unordered_set>
// #include <unordered_set>
//创建一个能容纳int型元素的set
set<int> se;
//插入一个元素
se.insert(2);
// se.emplace(3);
//找到指定关键字位置
se.find(2);
//删除关键字
se.erase(2);
return 0;
}
2)迭代器(Iterator),提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定义了operator()以及其他类似于指针的操作符地方法的类对象;*
//迭代器 : 是一个所谓的智能指针,具有遍历复杂数据结构的能力。
//每一种容器都必须提供自己的迭代器,事实上每种容器都将其迭代器以嵌套的方式定义于内部。
//因此各种迭代器的接口相同,型号却不同,这就是所谓的泛型程序设计的概念:所用的操作行为都使用相同的接口,虽然他们的具体实现不同。
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main()
{
std::vector<string> names;
names.push_back("龚港浩");
names.push_back("王雪茗");
std::vector<string> ::iterator iter = names.begin();
while(iter != names.end())
{
cout << *iter << "\n";
++iter;
}
return 0;
}
3)算法(Algorithm),是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;
STL中算法大致分为四类:
1、非可变序列算法:指不直接修改其所操作的容器内容的算法。
2、可变序列算法:指可以修改它们所操作的容器内容的算法。
3、排序算法:包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。
4、数值算法:对容器内容进行数值计算。
查找算法 - 判断容器内是否包含某个值
方法 | 含义 |
---|---|
adjacent_find | 在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的ForwardIterator。否则返回last。重载版本使用输入的二元操作符代替相等的判断。 |
binary_search | 在有序序列中查找value,找到返回true。重载的版本实用指定的比较函数对象或函数指针来判断相等。 |
count | 利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数。 |
count_if | 利用输入的操作符,对标志范围内的元素进行操作,返回结果为true的个数 |
equal_range | 功能类似equal,返回一对iterator,第一个表示lower_bound,第二个表示upper_bound |
find | 利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的一个InputIterator。 |
find_end | 在指定范围内查找"由输入的另外一对iterator标志的第二个序列"的最后一次出现。找到则返回最后一对的第一个ForwardIterator,否则返回输入的"另外一对"的第一个ForwardIterator。重载版本使用用户输入的操作符代替等于操作。 |
find_first_of | 在指定范围内查找"由输入的另外一对iterator标志的第二个序列"中任意一个元素的第一次出现。重载版本中使用了用户自定义操作符。 |
find_if | 使用输入的函数代替等于操作符执行find |
lower_bound | 返回一个ForwardIterator,指向在有序序列范围内的可以插入指定值而不破坏容器顺序的第一个位置。重载函数使用自定义比较操作。 |
upper_bound | 返回一个ForwardIterator,指向在有序序列范围内插入value而不破坏容器顺序的最后一个位置,该位置标志一个大于value的值。重载函数使用自定义比较操作 |
search | 给出两个范围,返回一个ForwardIterator,查找成功指向第一个范围内第一次出现子序列(第二个范围)的位置,查找失败指向last1。重载版本使用自定义的比较操作。 |
serach_n | 在指定范围内查找val出现n次的子序列。重载版本使用自定义的比较操作。 |
//查找算法
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
bool evenNum( int n ) //是否为偶数
{ return n % 2; }
bool sixNum( int n ) //是否等于5
{ return n == 5; }
int main()
{
int num = 6;
vector<int> v1;
v1.push_back(3);
v1.push_back(3);
v1.push_back(3);
v1.push_back(3);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
v1.push_back(7);
v1.push_back(8);
v1.push_back(9);
v1.push_back(10);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
//adjacent_find 查找相邻重复元素
vector<int>:: iterator pos = adjacent_find(v1.begin(),v1.end());
if(pos == v1.end()){
cout << "未找到相邻重复元素" << endl;
}else{
cout << "找到相邻元素" << *pos << endl;
}
//binary_search
if(binary_search(v1.begin(),v1.end(),4)){
cout << "容器中含有元素4" << endl;
}
//equal_range 二分查找
pair<vector<int>::iterator,vector<int>::iterator> range = equal_range(v1.begin(),v1.end(),3);
cout << "这是一个啥东西" << *range.first << *range.second << endl;
//lower_bound -函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置
vector<int>:: iterator pos_lower = lower_bound(v1.begin(),v1.end(),3);
cout << "大于等于3的第一个元素的位置" << *pos_lower << endl;
//upper_bound - 函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置
vector<int>:: iterator pos_upper = upper_bound(v1.begin(),v1.end(),3);
cout << "大于3的第一个元素的位置" << *pos_upper << endl;
//find
vector<int>::iterator iter = find( v1.begin(), v1.end(), num ); //查找等于6的元素位置
if( iter != v1.end() ){
cout << "匹配元素的索引: " << iter - v1.begin() << endl; //找到匹配元素位置
}
vector<int> v2;
v2.push_back(3);
v2.push_back(4);
v2.push_back(5);
v2.push_back(6);
//find_if
iter = find_if(v2.begin(),v2.end(),sixNum);
if(iter != v2.end()){
cout << "等于5的元素索引是" << iter - v2.begin() << endl;
}
//find_first_of
iter = find_first_of( v1.begin(), v1.end(), v2.begin(), v2.end() );
if( iter != v2.end() ){
cout << "第一个匹配元素索引:" << iter - v1.begin() << endl;
}
//find_end
iter = find_end( v1.begin(), v1.end(), v2.begin(), v2.end() );
if( iter != v2.end() ){
cout << "最后一个匹配元素索引:" << iter - v1.begin() << endl;
}
//count_if
int even_times = count_if( v1.begin(), v1.end(), evenNum );
cout << "偶数个数 :" << even_times << endl;
//count
int four_times = count(v1.begin(), v1.end(), 4);
cout << "元素4的个数 :" << four_times << endl;
//search - 在一个序列中搜索与另一序列匹配的子序列。
vector<int>:: iterator iterlocation = search(v1.begin(),v1.end(),v2.begin(),v2.end());
if (iterlocation != v1.end())
{
cout << "v2的元素包含在v1容器中,起始元素为"
<< "v1[" << iterlocation - v1.begin() << "]" <<endl;
}
else
{
cout << "v2的元素不包含在v1容器" << endl;
}
//search_n
vector<int>:: iterator iterlocation_n = search_n(v1.begin(),v1.end(),3,3);
if (iterlocation_n != v1.end())
{
cout << "在v1中找到3个连续的元素3" << endl;
}
else
{
cout << "在v1中没有3个连续的元素3" << endl;
}
return 0;
}
排序和通用算法 - 提供元素排序策略
方法 | 含义 |
---|---|
inplace_merge | 合并两个有序序列,结果序列覆盖两端范围。重载版本使用输入的操作进行排序 |
merge | 合并两个有序序列,存放到另一个序列。重载版本使用自定义的比较。 |
nth_element | 将范围内的序列重新排序,使所有小于第n个元素的元素都出现在它前面,而大于它的都出现在后面。重载版本使用自定义的比较操作。 |
partial_sort | 对序列做部分排序,被排序元素个数正好可以被放到范围内。重载版本使用自定义的比较操作。 |
partial_sort_copy | 与partial_sor类似,不过将经过排列的序列复制到另一个容器 |
partition | 对指定范围内元素重新排序,使用输入的函数,把结果为true的元素放在结果为false的元素之前。 |
random_shuffle | 对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作 |
reverse | 将指定范围内元素重新反序排序。 |
reverse_copy | 与reverse类似,不过将结果写入另一个容器。 |
rotate | 将指定范围内元素移到容器末尾,由middle指向的元素成为容器第一个元素。 |
rotate_copy | 与rotate类似,不过将结果写入另一个容器。 |
sort | 以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作。 |
stable_sort | 与sort类似,不过保留相等元素之间的顺序关系。 |
stable_partition | 与partition类似,不过不保证保留容器中的相对顺序。 |
//排序算法
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
bool cmp(int a,int b){
return a>b;
}
bool tmp(int a){
return a > 5;
}
void pprint(int t){
printf("%d ",t);
}
void merge_sort(vector<int>& nums, int l, int r)
{
if(l<r)
{
int mid = (l+r)/2;
merge_sort(nums, l, mid);
merge_sort(nums, mid+1, r);
inplace_merge(nums.begin()+l, nums.begin()+mid+1, nums.begin()+r+1);
}
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(5);
v1.push_back(6);
v1.push_back(10);
v1.push_back(20);
vector<int> v2;
v2.push_back(2);
v2.push_back(3);
v2.push_back(6);
v2.push_back(15);
v2.push_back(25);
vector<int> v3(10);
//使用for_each遍历
cout << "v1的数据 :";
for_each(v1.begin(),v1.end(),pprint);
cout << endl;
cout << "v2的数据 :" ;
for_each(v2.begin(),v2.end(),pprint);
//merge - 异地归并
merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
cout << endl;
cout << "v3的数据 :";
for_each(v3.begin(),v3.end(),pprint);
cout << endl;
//inplace_merge - 原地归并
vector<int> v4;
v4.push_back(20);
v4.push_back(3);
v4.push_back(60);
v4.push_back(15);
v4.push_back(25);
merge_sort(v4, 0, v4.size()-1);
cout << "v4的数据 :";
for_each(v4.begin(),v4.end(),pprint);
cout << endl;
//sort,如果cmp缺省则为升序排列
vector<int> v5;
v5.push_back(203);
v5.push_back(3);
v5.push_back(60);
v5.push_back(15);
v5.push_back(25);
v5.push_back(1);
v5.push_back(5);
v5.push_back(23);
sort(v5.begin(),v5.end(),cmp);
cout << "v5的数据 :";
for_each(v5.begin(),v5.end(),pprint);
cout << endl;
//partition,把结果为true的元素放在结果为false的元素之前
vector<int> v6;
v6.push_back(2);
v6.push_back(3);
v6.push_back(60);
v6.push_back(15);
v6.push_back(25);
v6.push_back(1);
v6.push_back(5);
v6.push_back(23);
partition(v6.begin(),v6.end(),tmp);
cout << "v6的数据 :";
for_each(v6.begin(),v6.end(),pprint);
cout << endl;
//反转
reverse(v5.begin(),v5.end());
cout << "反转后v5的数据 :";
for_each(v5.begin(),v5.end(),pprint);
cout << endl;
//旋转
rotate(v5.begin(),v5.begin()+5,v5.end());
cout << "旋转后v5的数据 :";
for_each(v5.begin(),v5.end(),pprint);
cout << endl;
vector<int> v7;
v7.push_back(2);
v7.push_back(3);
v7.push_back(60);
v7.push_back(15);
v7.push_back(25);
v7.push_back(1);
v7.push_back(5);
v7.push_back(23);
//局部排序
partial_sort(v7.begin(),v7.begin()+5,v7.end());
cout << "局部排序后v7的数据 :";
for_each(v7.begin(),v7.end(),pprint);
cout << endl;
vector<int> v8;
v8.push_back(2);
v8.push_back(3);
v8.push_back(60);
v8.push_back(15);
v8.push_back(10);
v8.push_back(1);
v8.push_back(5);
v8.push_back(23);
//数据分界
//里面有四个参数,分别是起始位置,排序位置,结束位置,排序规则(没有按默认排序),起始和结束都很好理解,那排序位置就是第i个位置的前面都小于a[i],后面都大于a[i],但不保证前后的数字是有序的
nth_element(v8.begin(),v8.begin()+5,v8.end(),cmp);
cout << "数据分界后v8的数据 :";
for_each(v8.begin(),v8.end(),pprint);
cout << endl;
return 0;
}
删除和替换算法
方法 | 含义 |
---|---|
copy | 复制序列 |
copy_backward | 与copy相同,不过元素是以相反顺序被拷贝 |
iter_swap | 交换两个ForwardIterator的值 |
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类似,不过把结果输出到另一个容器 |
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
bool evenNum( int n ) //是否为偶数
{ return n % 2 == 0; }
bool cmp(int a,int b){
return a<b;
}
void pprint(int t){
printf("%d ",t);
}
int main()
{
vector<int> v1;
v1.push_back(0);
v1.push_back(2);
v1.push_back(3);
v1.push_back(1);
v1.push_back(5);
v1.push_back(4);
v1.push_back(7);
cout << "初始v1的数据 :";
for_each(v1.begin(),v1.end(),pprint);
cout << endl;
vector<int> v2(v1.size());
copy(v1.begin(),v1.end(),v2.begin());
cout << "复制后v2的数据 :";
for_each(v2.begin(),v2.end(),pprint);
cout << endl;
vector<int> v3(v1.size());
copy_backward(v1.begin(),v1.end(),v3.begin());
cout << "反向复制后v3的数据 :";
for_each(v3.begin(),v3.end(),pprint);
cout << endl;
copy_backward(v1.end()-2,v1.end(),v1.end()-3);
cout << "反向复制后v1的数据 :";
for_each(v1.begin(),v1.end(),pprint);
cout << endl;
vector<int> v4;
v4.push_back(0);
v4.push_back(2);
v4.push_back(3);
v4.push_back(1);
v4.push_back(5);
v4.push_back(4);
v4.push_back(6);
remove(v4.begin(),v4.end(),1);
cout << "删除v4中的1后的数据 :";
for_each(v4.begin(),v4.end(),pprint);
cout << endl;
remove_if(v4.begin(),v4.end(),evenNum);
cout << "删除v4中的偶数的数据 :";
for_each(v4.begin(),v4.end(),pprint);
cout << endl;
vector<int> v5;
v5.push_back(0);
v5.push_back(2);
v5.push_back(0);
replace(v5.begin(),v5.end(),0,10);
cout << "代替v5中的的数据 :";
for_each(v5.begin(),v5.end(),pprint);
cout << endl;
//unique - 将后面不重复的元素覆盖前面重复的元素
vector<int> v6;
v6.push_back(1);
v6.push_back(2);
v6.push_back(2);
v6.push_back(2);
v6.push_back(1);
v6.erase(unique(v6.begin(),v6.end()),v6.end());
cout << "删除v6中的重复数据 :";
for_each(v6.begin(),v6.end(),pprint);
cout << endl;
int a = 10;
int b = 100;
cout << "交换前" << "a:" << a << "b:" << b << endl;
swap(a,b);
cout << "交换后" << "a:" << a << "b:" << b << endl;
return 0;
}
排列组合算法 - 提供计算给定集合按一定顺序的所有可能排列组合
方法 | 含义 |
---|---|
next_permutation | 取出当前范围内的排列,并重新排列为下一个排列。重载版本使用自定义的比较操作 |
prev_permutation | 取出指定范围内的序列并将它重新排列为上一个序列,如果不存在上一个序列则返回false,重载版本使用自定义的比较操作 |
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
void pprint(int t){
printf("%d ",t);
}
int main()
{
vector<int> v1;
v1.push_back(3);
v1.push_back(2);
v1.push_back(4);
v1.push_back(1);
//降序排列
printf("按降序排序过程\n");
do{
for_each(v1.begin(),v1.end(),pprint);
printf("\n");
}while(next_permutation(v1.begin(),v1.end()));
vector<int> v2;
v2.push_back(5);
v2.push_back(10);
v2.push_back(4);
v2.push_back(20);
//升序排列
printf("按升序排序过程\n");
do{
for_each(v2.begin(),v2.end(),pprint);
printf("\n");
}while(prev_permutation(v2.begin(),v2.end()));
return 0;
}
算术算法
方法 | 含义 |
---|---|
accumulate | iterator对标识的序列段元素之和,加到一个由val制定的初始值上,重载版本不在做加法,而是传进来的二元操作符被应用到元素上 |
partical_sum | 创建一个新序列,其中每个元素值代表指定范围内该位置前所有元素之和。重载版本使用自定义操作代替加法。 |
insert_product | 对两个序列做内积(对应元素相乘,再求和)并将内积加到一个输入的初始值上。重载版本使用用户定义的操作。 |
adjacent_difference | 创建一个新序列,新序列中每个新值代表当前元素与上一个元素的差。重载版本用指定二元操作计算相邻元素的差。 |
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <numeric>
using namespace std;
bool evenNum( int n ) //是否为偶数
{ return n % 2; }
bool cmp(int a,int b){
return a<b;
}
void pprint(int t){
printf("%d ",t);
}
int main()
{
vector<int> v1;
v1.push_back(9);
v1.push_back(10);
v1.push_back(100);
v1.push_back(3);
v1.push_back(20);
v1.push_back(67);
int sum1 = accumulate(v1.begin(),v1.end(),0);
cout << "v1内的所有数据和" << sum1 << endl;
return 0;
}
生成和异变算法
方法 | 含义 |
---|---|
fill | 将输入值赋给标志范围内的所有元素。 |
fill_n | 将输入值赋给first到first+n范围内的所有元素。 |
for_each | 用指定函数依次对指定范围内所有元素进行迭代访问,返回所指定的函数类型。该函数不得修改序列中的元素 |
generate | 连续调用输入的函数来填充指定的范围。 |
generate_n | 与generate函数类似,填充从指定iterator开始的n个元素。 |
transform | 将输入的操作作用与指定范围内的每个元素,并产生一个新的序列。重载版本将操作作用在一对元素上,另外一个元素来自输入的另外一个序列。结果输出到指定容器。 |
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int randoms(){
return rand()%10;
}
void pprint(int t){
printf("%d ",t);
}
int main()
{
vector<int> v1;
v1.push_back(9);
v1.push_back(10);
v1.push_back(100);
v1.push_back(3);
v1.push_back(20);
v1.push_back(67);
fill(v1.begin()+1,v1.begin()+3,0);
cout << "替代v1内的数据";
for_each(v1.begin(),v1.end(),pprint);
cout << endl;
vector<int> v2;
v2.push_back(12);
v2.push_back(1);
v2.push_back(3);
v2.push_back(20);
v2.push_back(6);
fill_n(v2.begin()+1,3,9);
cout << "从第二个位置开始替换3个9后v2内的数据";
for_each(v2.begin(),v2.end(),pprint);
cout << endl;
vector<int> v3(5);
generate(v3.begin(),v3.end(),randoms);
cout << "随机生成v3内的数据";
for_each(v3.begin(),v3.end(),pprint);
cout << endl;
vector<int> v4(10);
generate_n(v4.begin()+3,4,randoms);
cout << "从第四个位置随机生成4个数据后v4:";
for_each(v4.begin(),v4.end(),pprint);
cout << endl;
transform(v4.begin(),v4.end(),v4.begin(),negate<int>());
cout << "v4数据取反:";
for_each(v4.begin(),v4.end(),pprint);
cout << endl;
return 0;
}
关系算法
方法 | 含义 |
---|---|
equal | 如果两个序列在标志范围内元素都相等,返回true。重载版本使用输入的操作符代替默认的等于操作符。 |
includes | 判断第一个指定范围内的所有元素是否都被第二个范围包含,使用底层元素的<操作符,成功返回true。重载版本使用用户输入的函数。 |
lexicographical_compare | 比较两个序列。重载版本使用用户自定义比较操作。 |
max | 返回两个元素中较大一个。重载版本使用自定义比较操作。 |
max_element | 返回一个ForwardIterator,指出序列中最大的元素。重载版本使用自定义比较操作。 |
min | 返回两个元素中较小一个。重载版本使用自定义比较操作。 |
min_element | 返回一个ForwardIterator,指出序列中最小的元素。重载版本使用自定义比较操作。 |
mismatch | 并行比较两个序列,指出第一个不匹配的位置,返回一对iterator,标志第一个不匹配元素位置。如果都匹配,返回每个容器的last。重载版本使用自定义的比较操作。 |
#include <vector>
#include <algorithm>
#include <iostream>
#include <functional>
using namespace std;
void pprint(int t){
printf("%d ",t);
}
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(1);
v1.push_back(4);
v1.push_back(5);
vector<int> v2;
v2.push_back(1);
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
v2.push_back(5);
bool rtn1 = equal(v1.begin(),v1.end(),v2.begin());
if(rtn1){
cout << "两个元素相等" << endl;
}else{
cout << "两个元素不相等" << endl;
}
bool rtn2 = includes(v1.begin(),v1.end(),v2.begin(),v2.end());
if(rtn2){
cout << "v1包含v2" << endl;
}else{
cout << "v1不包含v2" << endl;
}
//求最大值
int max_num = *max_element(v1.begin(),v1.end());
cout << "最大值:" << max_num << endl;
//求最小值
int min_num = *min_element(v1.begin(),v1.end());
cout << "最小值:" << min_num << endl;
//返回较大值
int ax = max(3,5);
int bi = min(3,5);
cout << "比较大的" << ax << endl;
cout << "比较小的" << bi << endl;
}
集合算法
方法 | 含义 |
---|---|
set_union | 构造一个有序序列,包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作。 |
set_intersection | 构造一个有序序列,其中元素在两个序列中都存在。重载版本使用自定义的比较操作。 |
set_difference | 构造一个有序序列,该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用自定义的比较操作。 |
set_symmertric_difference | 构造一个有序序列,该序列取两个序列的对称差集(并集-交集)。 |
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
bool cmp(int a,int b){
return a<b;
}
void pprint(int t){
printf("%d ",t);
}
int main()
{
vector<int> v1,v2,v3;
v1.push_back(1);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
v1.push_back(8);
v2.push_back(1);
v2.push_back(2);
v2.push_back(3);
v2.push_back(7);
v2.push_back(9);
v2.push_back(10);
//并集
set_union(v1.begin(),v1.end(),v2.begin(),v2.end(), back_inserter(v3));
cout << "两个容器相加的结果" ;
for_each(v3.begin(),v3.end(),pprint);
cout << endl;
v3.clear();
//交集
set_intersection(v1.begin(), v1.end(),v2.begin(), v2.end(),back_inserter(v3));
cout << "两个容器相乘的结果";
for_each(v3.begin(),v3.end(),pprint);
cout << endl;
v3.clear();
//差集
set_difference(v1.begin(), v1.end(),v2.begin(), v2.end(),back_inserter(v3));
cout << "两个容器相减的结果";
for_each(v3.begin(),v3.end(),pprint);
cout << endl;
v3.clear();
return 0;
}
堆算法
方法 | 含义 |
---|---|
make_heap | 把指定范围内的元素生成一个堆。重载版本使用自定义比较操作。 |
pop_heap | 并不真正把最大元素从堆中弹出,而是重新排序堆。它把first和last-1交换,然后重新生成一个堆。可使用容器的back来访问被"弹出"的元素或者使用pop_back进行真正的删除。重载版本使用自定义的比较操作。 |
push_heap | 假设first到last-1是一个有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。在指向该函数前,必须先把元素插入容器后。重载版本使用指定的比较操作。 |
sort_heap | 对指定范围内的序列重新排序,它假设该序列是个有序堆。重载版本使用自定义比较操作。 |
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
void pprint(int t){
printf("%d ",t);
}
int main()
{
vector<int> v1;
v1.push_back(4);
v1.push_back(5);
v1.push_back(1);
v1.push_back(3);
v1.push_back(2);
// generate heap in the range of v1
make_heap(v1.begin(), v1.end());
cout << "initial max value : " << v1.front() << endl;
// pop max value
pop_heap(v1.begin(), v1.end());
cout << "after pop, the max vsalue : " << v1.front() << endl;
// push a new value
v1.push_back(6);
push_heap(v1.begin(), v1.end());
cout << "after push, the max value : " << v1.front() << endl;
return 0;
}
4)仿函数(Function object)
5)迭代适配器(Adaptor)
6)空间配制器(allocator)