C++STL之multiset,set,multimap,map

C++ STL学习笔记

这篇笔记是对慕课上郭炜老师的c++课程自己的总结,方便日后复习
平衡二叉树作用:需要在大量增删数据的同时大量查找数据并都能在log(n)复杂度完成。
四种**“排序容器”**:multiset,set,multimap,map
注:使用multiset和set要用头文件#include
使用multimap和map要用头文件#include

1.multiset用法

  1. 默认用法
multiset <T> st;//默认从小到大
multiset <T,greater<T>>st;//从大到小

➢定义了一个multiset的变量stst里面可以存放T类型的数据,并且能自动排序开始st为空
排序规则: 表达式“a < b”为true, 则a排在b前面。
➢可用st.insert添加元素,st.find查找元素,st.erase删除元素,复杂度都是log(n)。

#include 
#include 
#include 
using namespace std;
int main()
{
	multiset<int> st;
	int a[10]={1,14,12,13,7,13,21,19,8,8};
	for(int i=0;i<10;++i)
		st.insert(a[i]);//把数组a[i]的内容复制放入容器st中
		multiset<int>::iterator i;//迭代器,近似于指针,用于访问容器st
	for(i=st.begin();i!=st.end();++i) //st.begin()和st.end()为st指向头元素和尾元素后面一个位置的迭代器,类型为multiset::iterator
		cout<<*i<<",";
		cout<<endl;		//输出排好序的数组a[i]:1,7,8,8,12,13,13,14,19,21
}
  • multiset上的迭代器multiset ::iterator P;
    此处p是迭代器,相当于指针,只能通过迭代器访问multiset的元素。
    与指针的相同与不同:
    相同点:可++,–,用!= 和==比较
    不同点:不可比大小,不可加减整数,不可相减

继续使用上例迭代器i 其中元素为{1,7,8,8,12,13,13,14,19,21}

{
i=st.lower_bound(13);//返回最靠后的迭代器it使左闭右开的区间[begin(),it)中的元素都在13前面,复杂度为log(n)
cout<< *i <<endl;//输出13,迭代器指向第一个13
i=st.upper_bound(8)//返回最靠前的迭代器it使左闭右开的区间[it,end())中的元素都在8后面,复杂度为log(n)
cout<< *i <<endl;//输出12,迭代器指向第二个8后面的12
st.erase(i);//删除迭代器i指向的元素,12
for(i=st.begin();i!=st.end();++i)
	cout<< *i << ",";//输出1,7,8,8,13,13,14,19,21,22,
	return 0;
}
  1. 自定义规则用法
#include 
#include 
#include 
using namespace std ;
struct Rule1 {
	bool operator()(const int & a,const int & b)const
	{return (a%10)<(b%10);}//个位数从小到大排
	};
int a[10]={1,14,12,13,7,13,21,19,8,8};
muliset<int,Rule1>st2;
for(int i=0;i<10;++i)
	st2.insert(a[i]);
	multiset<int,Rule1>::iterator p;
for(p=st2.begin();p!=st2.end();++p)
	cout<<*p<<",";
cout<<endl;//输出1,21,12,13,13,14,7,8,8,19,  即按个位数从小到大排
p=str2.find(133);
cout << *p <<endl;//输出13
return 0;

自定义规则排序和sort自定义规则类似,但是在使用迭代器前要定义multiset<类型,规则>::iterator p;
类比复习点击此处

2.set用法

➢set和multiset的区别在于容器里不能有重复元素
a和b重复“a必 须排在b前面”和“b必须排在a前面”都不成立
➢set插入元素可能不成功(插入容器已有的元素就会不成功)
例子如下

#include 
#include 
#include 
using namespace std;
int main ()
{
	set<int> st;
	int a[10] ={ 1,2,3,8,7,7,5,6,8,12 };//有两个7,两个8
	for(int i = 0;i < 10; ++i)
		st.insert(a[i]);
	cout << st.size() << endl; //输出元素个数: 8
	set<int>::iterator i ;
	for(i = st.begin() ; i != st.end() ; ++i)
		cout << * i << ","; //输出: 1,2,3,5,6,7,8,12,
	cout << endl;
}

set插入元素用法

#include 
#include 
#include 
using namespace std;
int main ()
{
	int a[10] ={ 1,2,3,8,7,7,5,6,8,12 };
	pair<set<int>::iterator, bool>result= st.insert(2);
	if(!result.second)//条件成立说明输入不成功
	cout<< *result.first <<"already exists."<<endl;
	else cout<< *result.first<<"inserted."<<endl;//输出:2 already exists.
	return 0;
}

上述pair::iterator,bool>struct{ set::iterator first; bool second; }等价。

  • 拓展:pair模板的用法
pair<T1,T2>类型等价于:
struct{
	T1 first;
	T2 second;
};

例如:

pair<int,double> a;
等价于:
struct{
	int first;
	double second;
} a;

3.multimap用法

➢multimap容器里的元素都是pair形式的multimap mp;
➢mp里元素都是如下类型:

struct{
	T1 first;
	T2 second;
};

multimap中元素按照规则对first排序并且按first查找,排序与second无关
如下是郭炜老师慕课上的经典例题(点击查看原网址):
C++STL之multiset,set,multimap,map_第1张图片
题解:

#include 
#include 
#include 
using namespace std;
struct StudentInfo {
	int id; char name[20];
	};
struct Student{
	int score;
	StudentInfo info;
	};
typedef multimap<int,StudentInfo>MAP_STD;
int main()
{
	MAP_STD mp;
	Student st;
	char cmd[20];
	while( cin >> cmd )
	{
		if( cmd[0] == 'A'{
			cin >> st.info.name >> st.info.id >> st.score ;
			mp.insert(make_pair(st.score,st.info));//make_pair生成一个pair变量
		}
		else if( cmd[0] =='Q'{
			int score;
			cin >> score ;
			MAP_STD::iterator p = mp.lower_bound(score);//找比score小的下界
		if( p!= mp.begin()) 
		{
			--p;
			score = p -> first;//找比score小的最高分
			MAP_STD::iterator maxp = p;
			int maxId = p -> second.id;
			for( ; p!=mp.begin()&&p->first==score ; --p)//遍历所以成绩为score的学生
			{
				if(p ->second.id > maxId)
				{	maxp = p;
					maxId =p-》second.id;
				}
			}
			if( p->first == score) 
			{
				if( p->second.id > maxId ) 
				{
					maxp = P;
					maxId = p->second.id ;
				}
			}
			cout< << maxp->second.name<< " "<< maxp->second.id<< " "<< maxp->first << endl ;
		}
		else cout << "Nobody" << endl;
	}
	return 0;
}

4.map的用法

➢map和multimap的区别在于容器里不能有关键字重复元素
➢map可以使用 [ ]下标为关键字,作用是将关键码作为下标去执行查找,并返回对应的值;如果不存在这个关键码,就将一个具有该关键码和值类型的默认值的项插入这个map
➢map插入元素可能失败
例子如下:
例子一:成绩录入

#include 
#include 
#include 
using namespace std;
struct Student {
	string name;
	int score;
};
Student students[5] ={
{"Jack",89},{"Tom",74},{"Cindy",87},{"Alysa",87},{"Micheal",98}};
typedef map<string,int> MP;
int main()
{
	MP mp;
	for(int i =0;i<5;++i)
		mp.insert(make_pair(students[i].name,students[i].score));
	cout << mp["Jack"] <<endl;//输出 89
	mp["Jack"] =60;//修改名为“Jack”的元素的second值
	for (MP::iterator i = mp.begin(); i !=_ mp.end() ; ++i)
		cout<<"("<<i->first<<","<<i->second<<")";
	//输出: (Alysa,87) (Cindy,87) (Jack, 60) (Micheal,98) (Tom, 74)
	cout << endl;
	Student st;
	st.name ="Jack"; st.score = 99;
	pair<MP::iterator,bool> p= mp.insert(make_pair(st.name,st.score));
	if(p.second)
		cout << "(" << p.first->first <<","<< p.first->second<<")inserted"<<endl;
	else
		cout << " insertion failed" << endl; //输出此信息.
	mp ["Harry"] = 78; //因为没有Harry,则插入一元素, 其first为 "Harry" ,然后将其second改为78
	MP::iterator q = mp.find("Harry") ;
	cout << "(" << q->first << " ," << q->second <<")< <end1 ;//输出 (Harry,78)
	return 0;

例子二:单词词频统计程序
输入大量单词,每个不超过20字符,按出现次数从多到少排序,次数相同按字典序排

#include 
#include 
#include 
#include 
using namespace std;
struct Word{
	int times;
	string wd;
};
struct Rule {
	bool operator() (const Word &w1,const Word &w2){
		if( w1.times !=w2.times)
			return w1.times>w2.times;
		else 
			return w1.wd<w2.wd;
		}
};
int main()
{
	string s;
	set<Word,Rule> st;
	map<string,int> mp;
	while( cin >>s )
		++mp[s];
	for( map<string,int>::iterator i=mp.begin(); i != mp.end(); ++i)
	{
		Word tmp;
		tmp.wd =i->first;
		tmp.times =i-》second;
		st.insert(tmp);
	}
	for(set<Word,Rule>::iterator i = st.begin();i!=st.end();++i)
		cout << i->wd<<" "<< i->times << endl;
}
		

你可能感兴趣的:(笔记)