C语言STL标准模板库 (容器)从入门到入坑

六大组件:

容器,算法,迭代器,仿函数,适配器,空间配置器
C语言STL标准模板库 (容器)从入门到入坑_第1张图片

在这里插入图片描述

容器分类:

C语言STL标准模板库 (容器)从入门到入坑_第2张图片

算法分类:

在这里插入图片描述

迭代器

vector,deque,list,set,map有迭代器:

vector,为动态空间,原迭代器在扩容后会失效
deque的迭代器很复杂,所以用的少
list,迭代器不会因为插入和删除操作而失效
set,map的迭代器为只读迭代器,不会失效,不能通过迭代器修改数据

stack,queue没有迭代器

分类

C语言STL标准模板库 (容器)从入门到入坑_第3张图片

遍历

一般遍历:
vector 可以用下标遍历

void print(int x)
{
	cout<<x<<endl;
}
int main()
{
	vector<int> a;
	a.push_back(1);
	a.push_back(3);
	a.push_back(3);
	vector<int>::iterator itstart=a.begin();
	vector<int>::iterator itend=a.end();
//	for(;itstart!=itend;itstart++) 
//	cout<<*itstart<
	
	for_each(it_start,it_end,print);
	return 0;
}

自定义类遍历:

class Person
{
public :
	Person(int age)
	{
		this->age=age;
	}
	int age;
};
void print(Person &a)
{
	cout<<a.age<<endl;
}
void test()
{
	Person p1(1);
	Person p2(4);
	Person p3(11);
	Person p4(13);
	vector<Person>  v;
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	vector<Person>::iterator itstart=v.begin();
	vector<Person>::iterator itend=v.end();
	for(;itstart!=itend;itstart++)
	{
		print(*itstart);
	}
} 
int main()
{
	test();
	return 0;
}

迭代器指向为容器

test2()
{
	vector <int> v1;
	vector<int> v2;
	vector<vector<int> > vsum;
	v1.push_back(1);v1.push_back(4);
	v2.push_back(3);v2.push_back(12);
	vsum.push_back(v1);vsum.push_back(v2);
	vector<vector<int> >::iterator itstart=vsum.begin();
	for(;itstart!=vsum.end();itstart++)
	{
		for(vector<int>::iterator it=(*itstart).begin();it!=(*itstart).end();it++)
		 {
		 	cout<<*it<<" ";
		 }
		 cout<<endl;
	} 
} 
int main()
{
//	test();
	test2();
	return 0;
}

常用容器

String容器

C语言STL标准模板库 (容器)从入门到入坑_第4张图片

赋值

C语言STL标准模板库 (容器)从入门到入坑_第5张图片
C语言STL标准模板库 (容器)从入门到入坑_第6张图片

C语言STL标准模板库 (容器)从入门到入坑_第7张图片

拼接:

注释部分都是可以的
C语言STL标准模板库 (容器)从入门到入坑_第8张图片

查找:

find()从左往右找
rfind()从右往左找
找到返回对应下标
找不到返回一个很大的数
C语言STL标准模板库 (容器)从入门到入坑_第9张图片

比较:

C语言STL标准模板库 (容器)从入门到入坑_第10张图片

获取子串:

s.substr(x,y) 从x位置开始的y个字符
C语言STL标准模板库 (容器)从入门到入坑_第11张图片

插入删除:

s.erase(x,y) 删除在x位置开始的y个字符
C语言STL标准模板库 (容器)从入门到入坑_第12张图片

string和char的转化

C语言STL标准模板库 (容器)从入门到入坑_第13张图片

Vector容器

C语言STL标准模板库 (容器)从入门到入坑_第14张图片

迭代器:可以随机访问

还有反向迭代器,++为往前挪
C语言STL标准模板库 (容器)从入门到入坑_第15张图片
在这里插入图片描述

构造函数:

C语言STL标准模板库 (容器)从入门到入坑_第16张图片

赋值:

交换操作,实际中是交换了指针指的位置。
C语言STL标准模板库 (容器)从入门到入坑_第17张图片

大小的对应操作:

resize(int num) 重新指定容器长度但是容量不变,变短,保留前num个,变长,默认为0
resize(int num,int x) 与上一样,变长,默认为x
C语言STL标准模板库 (容器)从入门到入坑_第18张图片

存取查找操作:

二分查找返回下标迭代器:可以用在vector,普通数组,set,map
利用二分查找的方法在一个排好序的数组中进行查找的。(如果没有排好序,也是从头往后找的结果)

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater< type >() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num,greater< type >() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

查询vector是否有某个数

 vector<int> v;
    v.push_back(1231);
    v.push_back(124242352);
    v.push_back(123);
    sort(v.begin(),v.end());
    int idx=lower_bound(v.begin(),v.end(),1231)-v.begin();
    if(v[idx]==123) cout<<"havs";

查询数组是否有某个数

  int num[6]={1,2,4,2,15,34}; 
    sort(num,num+6);
    int idx=lower_bound(num,num+6,4)-num;
    if(num[idx]==4) cout<<"has";
#include
using namespace std;
const int maxn=100000+10;
const int INF=2*int(1e9)+10;
#define LL long long
int cmd(int a,int b){
	return a>b;
}
int main(){
	int num[6]={1,2,4,7,15,34}; 
	sort(num,num+6);                           //按从小到大排序 
	int pos1=lower_bound(num,num+6,7)-num;    //返回数组中第一个大于或等于被查数的值 
	int pos2=upper_bound(num,num+6,7)-num;    //返回数组中第一个大于被查数的值
	cout<<pos1<<" "<<num[pos1]<<endl;
	cout<<pos2<<" "<<num[pos2]<<endl;
	sort(num,num+6,cmd);                      //按从大到小排序
	int pos3=lower_bound(num,num+6,7,greater<int>())-num;  //返回数组中第一个小于或等于被查数的值 
	int pos4=upper_bound(num,num+6,7,greater<int>())-num;  //返回数组中第一个小于被查数的值 
	cout<<pos3<<" "<<num[pos3]<<endl;
	cout<<pos4<<" "<<num[pos4]<<endl;
	return 0;	
} 

C语言STL标准模板库 (容器)从入门到入坑_第19张图片

插入删除:

C语言STL标准模板库 (容器)从入门到入坑_第20张图片

使用swap收缩容量

C语言STL标准模板库 (容器)从入门到入坑_第21张图片

用resize()预留空间:

不提琴预留足够大的空间,capacity会多次开辟空间
C语言STL标准模板库 (容器)从入门到入坑_第22张图片

排序:

C语言STL标准模板库 (容器)从入门到入坑_第23张图片

C语言STL标准模板库 (容器)从入门到入坑_第24张图片
自定义类型:
C语言STL标准模板库 (容器)从入门到入坑_第25张图片

list

一、List定义:

List是stl实现的双向链表,与向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢。使用时需要添加头文件

#include

二、List定义和初始化:

list<int>lst1;          //创建空list

list<int> lst2(5);       //创建含有5个元素的list

list<int>lst3(3,2);  //创建含有3个元素的list

list<int>lst4(lst2);    //使用lst2初始化lst4

list<int>lst5(lst2.begin(),lst2.end());  //同lst4

三、List常用操作函数:

Lst1.pop_back() 删除最后一个元素 
Lst1.pop_front() 删除第一个元素 
Lst1.push_back() 在list的末尾添加一个元素 
Lst1.push_front() 在list的头部添加一个元素 
Lst1.back() 返回最后一个元素 
Lst1.begin() 返回指向第一个元素的迭代器 
Lst1.clear() 删除所有元素 
Lst1.end() 返回末尾的迭代器 
Lst1.assign() 给list赋值 
Lst1.erase() 删除一个元素  迭代器
Lst1.front() 返回第一个元素 
Lst1.remove() 从list删除元素 

Lst1.empty() 如果list是空的则返回true 


Lst1.get_allocator() 返回list的配置器 
Lst1.insert() 插入一个元素到list中 
Lst1.max_size() 返回list能容纳的最大元素数量 
Lst1.merge() 合并两个list 
Lst1.rbegin() 返回指向第一个元素的逆向迭代器 
Lst1.remove_if() 按指定条件删除元素 
Lst1.rend() 指向list末尾的逆向迭代器 
Lst1.resize() 改变list的大小 
Lst1.reverse() 把list的元素倒转 
Lst1.size() 返回list中的元素个数 
Lst1.sort() 给list排序 
Lst1.splice() 合并两个list 
Lst1.swap() 交换两个list 
Lst1.unique() 删除list中重复的元素

四、List使用示例:

示例1:遍历List

//迭代器法

for(list::const_iteratoriter = lst1.begin();iter != lst1.end();iter++)
{
cout<<*iter;
}
cout<

示例2:

#include
#include
#include
#include
#include
using namespace std;

typedef list LISTINT;
typedef list LISTCHAR;

void main()
{
//用LISTINT创建一个list对象
LISTINT listOne;
//声明i为迭代器
LISTINT::iterator i;

listOne.push_front(3);
listOne.push_front(2);
listOne.push_front(1);

listOne.push_back(4);
listOne.push_back(5);
listOne.push_back(6);

cout << "listOne.begin()--- listOne.end():" << endl;
for (i = listOne.begin(); i != listOne.end(); ++i)
    cout << *i << " ";
cout << endl;

LISTINT::reverse_iterator ir;
cout << "listOne.rbegin()---listOne.rend():" << endl;
for (ir = listOne.rbegin(); ir != listOne.rend(); ir++) {
    cout << *ir << " ";
}
cout << endl;

int result = accumulate(listOne.begin(), listOne.end(), 0);
cout << "Sum=" << result << endl;
cout << "------------------" << endl;

//用LISTCHAR创建一个list对象
LISTCHAR listTwo;
//声明i为迭代器
LISTCHAR::iterator j;

listTwo.push_front('C');
listTwo.push_front('B');
listTwo.push_front('A');

listTwo.push_back('D');
listTwo.push_back('E');
listTwo.push_back('F');

cout << "listTwo.begin()---listTwo.end():" << endl;
for (j = listTwo.begin(); j != listTwo.end(); ++j)
    cout << char(*j) << " ";
cout << endl;

j = max_element(listTwo.begin(), listTwo.end());
cout << "The maximum element in listTwo is: " << char(*j) << endl;
Sleep(10000);

}

#include
#include
#include

using namespace std;
typedef list INTLIST;

//从前向后显示list队列的全部元素
void put_list(INTLIST list, char *name)
{
INTLIST::iterator plist;

cout << "The contents of " << name << " : ";
for (plist = list.begin(); plist != list.end(); plist++)
	cout << *plist << " ";
cout << endl;

}

//测试list容器的功能
void main(void)
{
//list1对象初始为空
INTLIST list1;
INTLIST list2(5, 1);
INTLIST list3(list2.begin(), --list2.end());

//声明一个名为i的双向迭代器 
INTLIST::iterator i;

put_list(list1, "list1");
put_list(list2, "list2");
put_list(list3, "list3");

list1.push_back(7);
list1.push_back(8);
cout << "list1.push_back(7) and list1.push_back(8):" << endl;
put_list(list1, "list1");

list1.push_front(6);
list1.push_front(5);
cout << "list1.push_front(6) and list1.push_front(5):" << endl;
put_list(list1, "list1");

list1.insert(++list1.begin(), 3, 9);
cout << "list1.insert(list1.begin()+1,3,9):" << endl;
put_list(list1, "list1");

//测试引用类函数 
cout << "list1.front()=" << list1.front() << endl;
cout << "list1.back()=" << list1.back() << endl;

list1.pop_front();
list1.pop_back();
cout << "list1.pop_front() and list1.pop_back():" << endl;
put_list(list1, "list1");

list1.erase(++list1.begin());
cout << "list1.erase(++list1.begin()):" << endl;
put_list(list1, "list1");

list2.assign(8, 1);
cout << "list2.assign(8,1):" << endl;
put_list(list2, "list2");

cout << "list1.max_size(): " << list1.max_size() << endl;
cout << "list1.size(): " << list1.size() << endl;
cout << "list1.empty(): " << list1.empty() << endl;

put_list(list1, "list1");
put_list(list3, "list3");
cout << "list1>list3: " << (list1 > list3) << endl;
cout << "list1

}

deque容器

vector只有尾插,尾删,为单向开口的连续内存空间。
deque则是双向开口的连续线性空间
C语言STL标准模板库 (容器)从入门到入坑_第26张图片

C语言STL标准模板库 (容器)从入门到入坑_第27张图片

构造函数:

C语言STL标准模板库 (容器)从入门到入坑_第28张图片

赋值操作:

d.assign(n,x) 赋值n个x
在这里插入图片描述

大小操作:

C语言STL标准模板库 (容器)从入门到入坑_第29张图片

双端操作:

C语言STL标准模板库 (容器)从入门到入坑_第30张图片

取值:

C语言STL标准模板库 (容器)从入门到入坑_第31张图片
插入操作:
pos对应的是迭代器,不是int数值
C语言STL标准模板库 (容器)从入门到入坑_第32张图片

C语言STL标准模板库 (容器)从入门到入坑_第33张图片
C语言STL标准模板库 (容器)从入门到入坑_第34张图片
删除:
C语言STL标准模板库 (容器)从入门到入坑_第35张图片

stack容器

先进后出
C语言STL标准模板库 (容器)从入门到入坑_第36张图片

没有迭代器:

C语言STL标准模板库 (容器)从入门到入坑_第37张图片

基本操作:

C语言STL标准模板库 (容器)从入门到入坑_第38张图片

queue容器:

先进先出
C语言STL标准模板库 (容器)从入门到入坑_第39张图片### 没有迭代器:
C语言STL标准模板库 (容器)从入门到入坑_第40张图片

基本操作:

C语言STL标准模板库 (容器)从入门到入坑_第41张图片

例子:

C语言STL标准模板库 (容器)从入门到入坑_第42张图片

priority_queue 优先队列

优先队列的用法
priority_queue 对于基本类型的使用方法相对简单。他的模板声明带有三个参数:

  priority_queue     
  其中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。

Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。

#include 
#include  
using namespace std; 
int main(){
    priority_queue<int> q;     
    for( int i= 0; i< 10; ++i ) q.push( rand() );
    while( !q.empty() ){
        cout << q.top() << endl;
        q.pop();
    }     
    getchar();
    return 0;
}
如果要用到小顶堆,则一般要把模板的三个参数都带进去。
STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆
#include 
#include  
using namespace std; 
int main(){
    priority_queue<int, vector<int>, greater<int> > q;
    for( int i= 0; i< 10; ++i ) q.push( rand() );
    while( !q.empty() ){
        cout << q.top() << endl;
        q.pop();
    }     
    getchar();
    return 0;
}

对于自定义类型,则必须自己重载 operator< 或者自己写仿函数

#include 
#include  
using namespace std; 
struct node
{
	int x,y;
	node(int xx,int yy):x(xx),y(yy){
	}
	bool operator<(const node &cmp)const{
		return x>cmp.x;//升序,为小根堆 
	}
}; 
 
int main(){
    priority_queue<node> q;     
//    for( int i= 0; i< 10; ++i )
//    q.push( Node( i/2,i*3) );     
	q.push(Node(3,3));
	q.push(Node(3,13));
	q.push(Node(3,1));
	q.push(Node(1,1));
	
    while( !q.empty() ){
        cout << q.top().x << ' ' << q.top().y << endl;
        q.pop();
    }     
    return 0;
}

自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。 重载函数operator< 也可以放到Node结构体申明里,但要加friend修饰
但此时不能像基本类型这样声明
priority_queue;
原因是 greater 没有定义,如果想用这种方法定义 则可以按如下方式:

#include 
#include  
using namespace std; 
struct Node{
    int x, y;
    Node( int a= 0, int b= 0 ):
        x(a), y(b) {}
};
 
struct cmp{
    bool operator() ( Node a, Node b ){
        if( a.x== b.x ) return a.y> b.y;         
        return a.x> b.x; }//为升序
       //return a.x
};
 
int main(){
    priority_queue<Node, vector<Node>, cmp> q;     
    for( int i= 0; i< 10; ++i )
    q.push( Node( rand(), rand() ) );
     
    while( !q.empty() ){
        cout << q.top().x << ' ' << q.top().y << endl;
        q.pop();
    }     
    getchar();
    return 0;
}  

//以上代码实现的是一个小顶堆
自实现优先队列

#include 
#include 
#include 
 
using namespace std;
 
class priority_queue
{
    private:
        vector<int> data;         
    public:
        void push( int t ){ 
            data.push_back(t); 
            push_heap( data.begin(), data.end()); 
        }         
        void pop(){
            pop_heap( data.begin(), data.end() );
            data.pop_back();
        }         
        int top() { return data.front(); }
        int size() { return data.size(); }
        bool empty() { return data.empty(); }
};  
int main()
{
    priority_queue test;
    test.push( 3 );
    test.push( 5 );
    test.push( 2 );
    test.push( 4 );     
    while( !test.empty() ){
        cout << test.top() << endl;
        test.pop(); 
    }         
    return 0; 
}

list容器:

链表物理存储单元上非连续,非顺序的存储结构。 为双向链表
C语言STL标准模板库 (容器)从入门到入坑_第43张图片
C语言STL标准模板库 (容器)从入门到入坑_第44张图片
C语言STL标准模板库 (容器)从入门到入坑_第45张图片

迭代器:

C语言STL标准模板库 (容器)从入门到入坑_第46张图片

list为双向循环链表的验证:

会打印出两遍0-9.

C语言STL标准模板库 (容器)从入门到入坑_第47张图片

基本操作:

C语言STL标准模板库 (容器)从入门到入坑_第48张图片
C语言STL标准模板库 (容器)从入门到入坑_第49张图片
C语言STL标准模板库 (容器)从入门到入坑_第50张图片
在这里插入图片描述

C语言STL标准模板库 (容器)从入门到入坑_第51张图片
C语言STL标准模板库 (容器)从入门到入坑_第52张图片

自定义类型排序:

C语言STL标准模板库 (容器)从入门到入坑_第53张图片

C语言STL标准模板库 (容器)从入门到入坑_第54张图片

set容器和multiset容器:

自动排序+去重 其中的迭代器为只读迭代器。
C语言STL标准模板库 (容器)从入门到入坑_第55张图片
C语言STL标准模板库 (容器)从入门到入坑_第56张图片

基本操作:

C语言STL标准模板库 (容器)从入门到入坑_第57张图片
C语言STL标准模板库 (容器)从入门到入坑_第58张图片
例子:
C语言STL标准模板库 (容器)从入门到入坑_第59张图片

C语言STL标准模板库 (容器)从入门到入坑_第60张图片

修改排序

默认为从小到大,

	set<int,greater<int> > a;//降序
	set<int> a;//默认为升序,等同set > a; 

C语言STL标准模板库 (容器)从入门到入坑_第61张图片
C语言STL标准模板库 (容器)从入门到入坑_第62张图片

取数:

	set<int>::iterator it;         
	// 用auto 也行     
    for(it=s.begin();it!=s.end();it++)  //使用迭代器进行遍历   
    {  
        printf("%d\n",*it);  
    }  

pair对组(也不算是容器)

声明方式:
C语言STL标准模板库 (容器)从入门到入坑_第63张图片
常用方式

pair<int,string> num_str[]={
            {1000, "M"},
            {900,  "CM"},
            {500,  "D"},
};
for(auto [k,v]:num_str){

}

map/multimap容器

C语言STL标准模板库 (容器)从入门到入坑_第64张图片

基本操作:

插入数据:
在这里插入图片描述

C语言STL标准模板库 (容器)从入门到入坑_第65张图片
遍历取值操作:

//map遍历按key从小到大
map<string,int>::iterator it=map.begin();
it->first it->second;
(*it).first  (*it).second;

// unordered_map 遍历随机
unordered_map<int,string> mp;
mp[1] = "apple";
for(auto it=mp.begin();it!=mp.end();it++) 

使用正向,反向迭代器遍历。或者用数组遍历。
常用:

正向:
for(auto it=m1.begin();it!=m1.end();it++){
        printf(" %d %.1lf",it->x,it->y);
    }
反向:
for(auto it=m1.end();it!=m1.begin();){
        --it;
        printf(" %d %.1lf",it->x,it->y);
    }
int main(){
    map<int,string> mapStudent;
    mapStudent[1] =  "student_one";
    mapStudent[2] =  "student_two";
    mapStudent[3] =  "student_three";
     map<int, string>::reverse_iterator   iter;
     for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++){
          cout<<iter->first<<" "<<iter->second<<endl;
     }
     return 0;
}

C语言STL标准模板库 (容器)从入门到入坑_第66张图片
修改排序规则:
默认为按键值升序:
C语言STL标准模板库 (容器)从入门到入坑_第67张图片

二维容器:

1,常用
vector<int> a[1000];
a[1].push_back(1);

2,非常用
vector<vector<int> > v;
	//要使用指定位置存值,就要先resize ,但是用了哪一层用了resize ,那一层就不能用push_back 
	
	//第一层,第二层都使用resize,就不能使用push_back() 放不进去的
	v.resize(100);
	v[1].resize(100);
	v[1][1]=2;//不能使用push_back() 放不进去的
	
	
	// 第一层使用resize,第二层不使用,可以用push_back()存值 
	v[1].push_back(1);
	v[1].push_back(2);
	v[1].push_back(3);
	v[1].push_back(4);
	cout<<v[1][1];

容器的复制拷贝:

复制容器(container)元素, 可以使用标准库(STL)的copy()和copy_n()函数.
在我们要初始化一个容器为另一个容器的拷贝时,如果不适用迭代器,直接使用容器变量名进行拷贝只能拷贝相同容器类型的

#include 
#include 
#include 
using namespace std;

int main()
{
    list<int> l = {1, 2, 3};
    list<int> v(l);  
    //vector v1(l); //出错
    for(auto i : v)
    {
        cout << i << endl;
    }
    return 0;
}

如果要拷贝不同容器类型的时候我们要使用迭代器来进行容器内范围拷贝

#include 
#include 
#include 
using namespace std;

int main()
{
    list<int> l = {1, 2, 3};
    vector<int> v(l.begin(), l.end());   
    for(auto i : v)
    {
        cout << i << endl;
    }
    return 0;
}

STL容器使用时机:

C语言STL标准模板库 (容器)从入门到入坑_第68张图片C语言STL标准模板库 (容器)从入门到入坑_第69张图片
C语言STL标准模板库 (容器)从入门到入坑_第70张图片

函数对象

C语言STL标准模板库 (容器)从入门到入坑_第71张图片

class Compare
{
public:
	bool operator()(int a,int b)
	{
		return a>b;
	}
};

void test11()
{
	vector<int> a;
	a.push_back(1);
	a.push_back(12);
	a.push_back(3);
	sort(a.begin(),a.end(),Compare());
	for(int i=0;i<a.size();i++)
	{
		cout<<a[i]<<endl;
	}
}

谓词:

boolean为返回追的函数对象
在这里插入图片描述

bool greater2(int a)
{
	return a>2;
}
void test11()
{
	vector<int> a;
	a.push_back(1);
	a.push_back(12);
	a.push_back(3);
	//find_if()返回一个迭代器 
	vector<int>::iterator it=find_if(a.begin(),a.end(),greater2);
	if(it!=a.end())
	{
		cout<<*it<<endl;
	}
}
int main()
{
	test11();
	return 0;
}

内建函数对象

C语言STL标准模板库 (容器)从入门到入坑_第72张图片

C语言STL标准模板库 (容器)从入门到入坑_第73张图片
C语言STL标准模板库 (容器)从入门到入坑_第74张图片

函数对象适配器

C语言STL标准模板库 (容器)从入门到入坑_第75张图片
C语言STL标准模板库 (容器)从入门到入坑_第76张图片

完整例题:

L2-005 集合相似度

C语言STL标准模板库 (容器)从入门到入坑_第77张图片

int n;
set<int> u[60];
void fun(int a,int b)
{
	int scnt=0;
	set<int>::iterator it;
	for(it=u[a].begin();it!=u[a].end();it++) 
	{
		if(u[b].find(*it)!=u[b].end()) scnt++;
	}
	int sum=u[a].size()+u[b].size()-scnt;
	printf("%.2f%%\n",scnt*1.0/sum*100);
}
int main()
{
	cin>>n;
	int k;
	for(int i=0;i<n;i++)
	{
		cin>>k;
		for(int j=0;j<k;j++)
		{
			int a;
			cin>>a;
			u[i+1].insert(a);
		} 
	}
	int m;
	cin>>m;
	while(m--)
	{
		int s;int ss;
		cin>>s>>ss;
		fun(s,ss);
	}
	return 0;
}

L2-015

C语言STL标准模板库 (容器)从入门到入坑_第78张图片

#include
#include

using namespace std;


int main()
{
	int n;
	cin>>n;
	set<int> s;
	for(int i=0;i<n;i++)
	{
		int t;
		cin>>t;
		set<int>::iterator it=s.lower_bound(t);
		if(it!=s.end())
		{
			s.erase(it);
		}
		s.insert(t);
	}
	cout<<s.size();
	return 0;
} 

L2-015:

C语言STL标准模板库 (容器)从入门到入坑_第79张图片

#include
#include
#include
#include

using namespace std;

const double eps = 1e-8; //const只是用来定义常量,常量在代码中一直存在,但define是预处理功能,有本质区别
const int maxx = 0x7f7f7f7f;//0x7f7f7f7f表示数据的无穷大
//常用的浮点数比较宏定义:
#define Equ(a,b) ((fabs((a)-(b)))<(eps)) //等于
#define More(a,b) (((a)-(b))>(esp)) //大于
#define Less(a,b) (((a)-(b))<(-esp))//小于
#define MoreEqu(a,b) (((a)-(b))>(-esp))//大于等于
#define LessEqu(a,b) (((a)-(b))<(esp))//小于等于
#define  MAX( x, y )  ( ((x) > (y)) ? (x) : (y) )//
//使用了algorithm头文件就可以直接使用max函数;
#define  MIN( x, y )  ( ((x) < (y)) ? (x) : (y) )
#define ll long long
#define PI 3.1415926
#define eps 1e-8
#define Conn(x,y) x##y;
int n;
int k;
int m;


int main()
{
	cin>>n>>k>>m;
	vector<double> v;
	for(int i=0;i<n;i++)
	{
		int minn=200;
		int maxx=-1;
		double sum=0;
		for(int j=0;j<k;j++)
		{
			int x;cin>>x;
			sum+=x;
			minn=min(minn,x);
			maxx=max(maxx,x);
		}
		sum=(sum-minn-maxx)/(k-2);
		v.push_back(sum);
	}
	sort(v.begin(),v.end());
	int start=n-m;
	for(int i=start;i<v.size();i++)
	{
		if(i!=v.size()-1)
		printf("%.3lf ",v[i]);
		else printf("%.3lf",v[i]);
	}
	return 0;
}

你可能感兴趣的:(算法,从入门到入坑,c语言,c++,算法)