一,map与hash
map的基本功能是实现一个key-value存储,与hash很像,事实上在数据量不很大时map 经常当hash用,而hash在一些库中的名字也是unordered_map.
map是用红黑树实现的,其插入,删除,查找的复杂度都是O(logn),而hash的插入,删除查找都是O(1). 因此当数据量很大时,map的性能不如hash,但数据量不很大(个人感觉在100W以内)时,两者的性能差异很小. map的一个好处是STL自带,使用起来非常方便:) map牺牲了这些性能带来的本质好处就是有序,因此更为灵活好用.
二,map的API和小技巧
map<string,int> m;
1,map可以用下标操作,例如m["张三"]=90,但是需要注意的是引用map中诶哟的下标会插入元素,即使你仅仅是试图打印,因此还是建议用pair或make_pair进行插入
2,map有一个可选的cmp参数指定比较函数,默认的比较函数是operator<, 可以用std:greater实现逆序排列
3,因为map是有序的关联容器,因此在一个iter遍历中进行earse会破坏有序性,导致不可预见的错误
for(iter=m.begin();iter!=m.end();iter++)
if(iter->first=="张三")
m.earse(iter) //错误
正确的写法:
for(iter=m.begin();iter!=m.end();)
if(iter->first=="张三")
m.earse(++iter)
else:
iter++;
4,map的key是不可以有重复的,多次insert一个key值时后面的语句无效,但用下标赋值时后面的有效
m.insert(make_pair("张三",90)) //第一次插入,有效
m.insert(make_pair("张三",80)) //重复插入,无效,还90
m["张三"]=80 //ok,m["张三"]=80,因为m["张三"]返回的是value值的引用
如果真需要重复的key可以用multimap,不过感觉用的很少~
5, map可以从一个区间定义的,例如 vector<pair<string,int> >vec, map<string,int> m(vec.begin(),vec.end())
map可以赋值的(拷贝欧洲函数),与python中的"浅拷贝"不同,这里实现的深拷贝
map的erase函数可以接受iter, key 或区间,erase会自动调用析构函数,返回值是删除元素的个数
三:set
1,set与map的内部实现是一样(的红黑树),可以将set看成一个特殊的map(没有value), 因此map和set的各项性质及性能都是基本一样的
2,set有一个很有意思的一点,就是他的insert函数可以有一个提示值(hint),提示值是一个iter,其所指的值离要插入的元素在序列中的排名越近,越能提高速度,但如果随便给hint的话,速度略有下降. 例如如果插入一个有序序列,可以这样写:
for each i in orderd range:
iter=s.insert(iter,i)
3,set的另一个insert函数是返回两个值的(pair<iter,bool>)iter是位置,bool是是否成功(级是否重复元素)
map的基本功能是实现一个key-value存储,与hash很像,事实上在数据量不很大时map 经常当hash用,而hash在一些库中的名字也是unordered_map.
map是用红黑树实现的,其插入,删除,查找的复杂度都是O(logn),而hash的插入,删除查找都是O(1). 因此当数据量很大时,map的性能不如hash,但数据量不很大(个人感觉在100W以内)时,两者的性能差异很小. map的一个好处是STL自带,使用起来非常方便:) map牺牲了这些性能带来的本质好处就是有序,因此更为灵活好用.
二,map的API和小技巧
map<string,int> m;
1,map可以用下标操作,例如m["张三"]=90,但是需要注意的是引用map中诶哟的下标会插入元素,即使你仅仅是试图打印,因此还是建议用pair或make_pair进行插入
2,map有一个可选的cmp参数指定比较函数,默认的比较函数是operator<, 可以用std:greater实现逆序排列
3,因为map是有序的关联容器,因此在一个iter遍历中进行earse会破坏有序性,导致不可预见的错误
for(iter=m.begin();iter!=m.end();iter++)
if(iter->first=="张三")
m.earse(iter) //错误
正确的写法:
for(iter=m.begin();iter!=m.end();)
if(iter->first=="张三")
m.earse(++iter)
else:
iter++;
4,map的key是不可以有重复的,多次insert一个key值时后面的语句无效,但用下标赋值时后面的有效
m.insert(make_pair("张三",90)) //第一次插入,有效
m.insert(make_pair("张三",80)) //重复插入,无效,还90
m["张三"]=80 //ok,m["张三"]=80,因为m["张三"]返回的是value值的引用
如果真需要重复的key可以用multimap,不过感觉用的很少~
5, map可以从一个区间定义的,例如 vector<pair<string,int> >vec, map<string,int> m(vec.begin(),vec.end())
map可以赋值的(拷贝欧洲函数),与python中的"浅拷贝"不同,这里实现的深拷贝
map的erase函数可以接受iter, key 或区间,erase会自动调用析构函数,返回值是删除元素的个数
三:set
1,set与map的内部实现是一样(的红黑树),可以将set看成一个特殊的map(没有value), 因此map和set的各项性质及性能都是基本一样的
2,set有一个很有意思的一点,就是他的insert函数可以有一个提示值(hint),提示值是一个iter,其所指的值离要插入的元素在序列中的排名越近,越能提高速度,但如果随便给hint的话,速度略有下降. 例如如果插入一个有序序列,可以这样写:
for each i in orderd range:
iter=s.insert(iter,i)
3,set的另一个insert函数是返回两个值的(pair<iter,bool>)iter是位置,bool是是否成功(级是否重复元素)