这篇笔记是对慕课上郭炜老师的c++课程自己的总结,方便日后复习
平衡二叉树作用:需要在大量增删数据的同时大量查找数据并都能在log(n)复杂度完成。
四种**“排序容器”**:multiset,set,multimap,map。
注:使用multiset和set要用头文件#include
使用multimap和map要用头文件#include
multiset <T> st;//默认从小到大
multiset <T,greater<T>>st;//从大到小
➢定义了一个multiset
➢排序规则: 表达式“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 ::iterator P;
继续使用上例迭代器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;
}
#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;
类比复习点击此处
➢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
与struct{ set
等价。
pair<T1,T2>类型等价于:
struct{
T1 first;
T2 second;
};
例如:
pair<int,double> a;
等价于:
struct{
int first;
double second;
} a;
➢multimap容器里的元素都是pair形式的multimap
➢mp里元素都是如下类型:
struct{
T1 first;
T2 second;
};
multimap中元素按照规则对first排序并且按first查找,排序与second无关
如下是郭炜老师慕课上的经典例题(点击查看原网址):
题解:
#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;
}
➢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;
}