set和map

c++ stl

set and map

关联容器

(1)仅包含关键字key的叫set 包含键值对key-value的叫map 前者叫集合set后者叫映射map

(2)key可以重读的就加一个multi

(3)是否按照hash函数映射的方式组织元素,是就加上unordered。

set和mutiset的构造 一个不可以重复一个可以重复

代码:

#include<iostream>
#include<set>
#include<functional>     //grreater<int> 
using namespace std;


//函数模板
template<class T>
void display(char *name,T & s){
	cout<<name;
	multiset<int>::iterator it = s.begin();
	while(it != s.end()){
		cout<<*it<<" ";
		it++;
	}
	cout<<endl;
} 
int main(){
	int a[] = {5,3,9,3,7,2,9,5};
	int size = sizeof(a)/sizeof(int);
	multiset<int>s1;
	for(int i = 0;i<size;i++) s1.insert(a[i]);   //与插入的顺序无关 
	display("s1:",s1);  //这个字符串会warning 
	
	multiset< int,less<int> >s2(s1);   //由低到高
	display("s2:",s2);
	
	multiset<int> s3(a,a+size);
	display("s3:",s3);
	
//	multiset< int,greater<int> >s4(s3);   //由低到高
//	display("s4:",s4);
	multiset< int,greater<int> >s4(a,a+size);   //不可以直接s4(s1) 
	display("s4:",s4);
	
	set<int>s5;
	for(int i = 0;i<size;i++) s5.insert(a[i]);   //不允许重复所以每一个值只保留一个
	display("s5:",s5);
	 
	
	return 0;
} 

什么函数对象?

如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象。函数对象是一个对象,但是使用的形式看起来像函数调用,实际上也执行了函数调用,因而得名。

#include<iostream>
using namespace std;


class hsdx{
	public:
		double operator () (int a1,int a2,int a3){
			return (double)(a1+a2+a3)/3;
		}
};

int main(){
	hsdx average;
	int a1,a2,a3;
	cin>>a1>>a2>>a3;
	cout<<average(a1,a2,a3);   //看起来像是函数的调用实际上是一个对象不过重载了()
	cout<<endl;
	//等价于下面这种形式 
	cout<<average.operator()(a1,a2,a3);
	return 0; 
}

1.由于集合是红黑树结构没有线性表当中的“头”和“尾”的概念,因此在集合中没有pop和push系列的成员函数,在添加和删除时通常采用insert和erase成员函数实现

2.集合的find函数要比泛型的find函数的查找效率高,这是因为基于集合自身的数据结构所导致的。

3.lower_bound(key) 和 upper_bound(key) 可以分别指向>=key 和 >key 的元素的迭代器位置

4.equal_range(key)可以以pair的形式返回=key的上界和下界迭代器

5.swap成员用于交换两个集合元素

6.count(key)用于返回关键值 = key的元素的个数

#include<iostream>
#include<set>
using namespace std;


template<class T>
void display(char* name,T &s){
	cout<<name;
	multiset<int>::iterator it = s.begin();
	while(it != s.end()){
		cout<<*it<<" "; 
		it++;
	}
	cout<<endl;
}

int main(){
	int a[] = {9,3,9,7,10,7,3};
	int size = sizeof(a)/sizeof(int);
	multiset<int>s(a,a+size);
	display("set:",s);
	cout<<"find(9) :"<<*(s.find(9))<<endl;  
	//输出9的前一个元素
	cout<<"9的前一个元素:"<<*(--s.find(9))<<endl; 
	cout<<"count(9) :"<<s.count(9)<<endl;   //输出关键字9的个数
	
	cout<<"lower_bound(6)"<<*s.lower_bound(6)<<endl;
	cout<<"upper_bound(6)"<<*s.upper_bound(6)<<endl;
	cout<<"equal_range(6)"<<*s.equal_range(6).first<<*s.equal_range(6).second<<endl;
	cout<<endl;
	cout<<"lower_bound(7)"<<*s.lower_bound(7)<<endl;
	cout<<"upper_bound(7)"<<*s.upper_bound(7)<<endl;
	cout<<"equal_range(7)"<<*s.equal_range(7).first<<*s.equal_range(7).second<<endl;
	cout<<endl;
	//删除关键字3
	
	cout<<"erase(3)"<<s.erase(3)<<endl;
	display("s:",s); 
	s.erase(s.find(9));	display("s:",s); //只删除了一个9这个只是传了一个迭代器 
	s.erase(*s.find(7));display("s:",s); //删除了所有的7
	s.clear();
	cout<<"size:"<<s.size();
	cout<<endl;
	return 0;
}

映射map与多重映射mutimap

1.pair类型

pair是定义在头文件中的一个类模板,有两个类型参数分别对应内部的两个数据成员

pair的两个成员分别命名为first和second

multimap的构造

#include<iostream>
#include<map>
#include<string>
#include<functional>  //greater<int>
using namespace std;


typedef multimap<int,string,less<int> >  ML;
typedef multimap<int,string,greater<int> > MG;

template<class T>
void display(char *name,T&m){
	cout<<name;
	multimap<int,string>::iterator it = m.begin();
	while(it != m.end()){
		cout<<"("<<(*it).first<<" "<<(*it).second<<")";
		it++; 
	}
	cout<<endl;
}



int main(){
	
	int s1[] = {23,20,10,28};
	string s2[] = {"重庆","上海","北京","成都"};
	int size = 4;
	ML m1;
	for(int i = 0;i<size;i++)
		m1.insert(make_pair(s1[i],s2[i]));
	display("m1:",m1);
	ML m2(m1);
	display("m2:",m2);
	ML m3(m2.begin(),m2.end());
	display("m3:",m3);
	MG m4;   //从大到小
	for(int i = 0;i<size;i++)
		m4.insert(make_pair(s1[i],s2[i]));
	display("m4:",m4);
	
	return 0;
}

map与multimap的成员函数

map和set非常类似也有相当多的成员函数,不同在于映射的容器元素为pair对象,在向映射容器中添加元素的时候需要先构成<key - value>对,然后再用insert成员函数插入;也可以通过emplace成员函数直接插入而无需构成对类型。

书上代码的emplace有问题


erase成员函数用于元素删除,当参数为迭代器的时候,删除对应位置的单个元素,当其参数为关键字值得时候,删除满足条件的所有元素。


unordered_set 和 unordered_multiset

关键字unordered表示无序,当向容器插入元素时,通过计算关键字的哈希值将其映射到不同的桶(bucket)中

每个桶可以保存一个或者多个元素。如果容器允许重复,那么相同的关键字也会映射到同一个桶当中。

无序容器的性能和哈希函数的选取以及桶的数量密切相关,哈希函数质量越好,则可以将元素更加均匀的映射到各个桶当中避免大量的元素聚集在个别桶当中。

无序容器也提供 了很多与有序容器相同的操作,因此他们之间的转换非常的方便。


最大装填因子load_factor

max_load_factor = 1,当容器当中的元素增加时,c++会自动添加新的桶,保证load_factor 始终小于等于max_load_factor.

posted @ 2020-10-17 14:22  secx  阅读(76)  评论(0)    收藏  举报