stl set,map ,hash_map学习
1. map功能:
- 自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
- 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
- 快速插入Key - Value 记录。
- 快速删除记录
- 根据Key 修改value记录。
- 遍历所有记录。
2. 使用
#include <map> //注意,STL头文件没有扩展名.h
插入元素:两种方式
(1)
enumMap[1] = "One";
enumMap[2] = "Two";
但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现
,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two"; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。
(2)
enumMap.insert(map<int, CString> :: value_type(2, "Two"))
删除元素:
erase() 函数
iterator erase(iterator it); //通过一个条目对象删除
iterator erase(iterator first, iterator last); //删除一个范围
size_type erase(const Key& key); //通过关键字删除
而clear()函数相当于:
enumMap.erase(enumMap.begin(), enumMap.end());
查找并获取map中的元素
string str = enumMap[2];
3. map底层
map底层使用红黑树,
更多细节参见
http://www.cnblogs.com/zjfdlut/archive/2011/08/12/2135698.html
4. hash_map
基于hash table(哈希表),提供在内存足够情况下,比map更快的访问查询
具体见:
http://www.cnblogs.com/yydy1983/archive/2010/03/04/1678195.html
5 GCC中使用 hash_map
由于hash_map并不是STL的一部分,各个C++编译器虽然都提供了这个容器,但是使用起来还是有些不同
例如在code blocks 中,使用编译器GCC时,可以
使用:
namespace std
{
using namespace __gnu_cxx;
}
#include <hash_map>
然后
std::hash_map<int,int> hm;
而对于用户自定义的类的hash_set,加上自己的 compare,和hash函数,例如对于字符串
//使用系统定义的字符串hash函数 struct str_hash { size_t operator ()( const string & str) const { return __stl_hash_string(str.c_str()); } }; //可以自定义hash函数 struct str_hash2 { size_t operator()( const string & str) const { unsigned long __h = 0; for ( size_t i = 0;i < str.size();i ++) __h = 5*__h + str[i]; return size_t (__h); } }; |
6 具体类使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | #include <iostream> #include <hash_map> #include <string> #include <map> namespace std { using namespace __gnu_cxx; } using namespace std; /* ============================================================== */ class ClassA { public : ClassA( int a){c_a = a;} int getValue() const { return c_a;} void setValue( int a){c_a = a;} private : int c_a; }; //定义hash函数 struct hash_A { size_t operator() ( const class ClassA & A) const { return A.getValue(); } }; //定义比较函数 struct equal_A { bool operator() ( const class ClassA &a1, const class ClassA &a2 ) const { return a1.getValue() == a2.getValue(); } }; /* ============================================================== */ //使用系统定义的字符串hash函数 struct str_hash { size_t operator ()( const string & str) const { return __stl_hash_string(str.c_str()); } }; //可以自定义hash函数 struct str_hash2 { size_t operator()( const string & str) const { unsigned long __h = 0; for ( size_t i = 0;i < str.size();i ++) __h = 5*__h + str[i]; return size_t (__h); } }; int main() { /* ============================================================ */ /*map操作*/ map< int , string> myMap; //插入元素的方法 pair< int , string> mypair; mypair = make_pair(1, "wang" ); pair<map< int , string>::iterator, bool > p1 = myMap.insert(mypair); myMap.insert(pair< int , string>(2, "yang" )); myMap[3] = "zhang" ; myMap.insert(pair< int ,string>(2, "xu" )); /*输出元素*/ for (map< int , string>::iterator iter = myMap.begin(); iter != myMap.end(); ++iter) { cout<<(*iter).first<< " " <<(*iter).second<<endl; } /* ============================================================== */ std::hash_map<ClassA,string,hash_A,equal_A> hmap; ClassA a1(12); hmap[a1] = "I am 12" ; ClassA a2(111111); hmap[a2] = "111111" ; cout << hmap[a1] << endl; cout << hmap[a2] << endl; /* ============================================================== */ std::hash_map<string,string,str_hash> hash_str; string str1( "str1" ); string str2( "str2" ); hash_str[str1] = "hash_str1" ; hash_str[str2] = "hash_str2" ; cout << hash_str[str1] << endl; cout << hash_str[str2] << endl; /* ============================================================== */ std::hash_map<string,string,str_hash2> hash_str2; string str3( "str3" ); string str4( "str4" ); hash_str2[str3] = "hash_str3" ; hash_str2[str4] = "hash_str4" ; cout << hash_str2[str3] << endl; cout << hash_str2[str4] << endl; return 0; } |
7. set
其底层数据结构同map是红黑树,元素唯一,在STL中,
通过algorithm中提供的set_intersection、set_union、set_difference、set_symmetric_difference四个函数,
可以方便的实现集合的交、并、差、对称差操作,很强大
set会对元素进行排序,排序规则通过Compare指定,事实上set的标准形式是set<Key, Compare, Alloc>,其中Compare表示比较函数,可以通过类或者结构体实现
Alloc为set的分配器,由于内部的内存管理,下面的示例对char×进行set
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #include<set> #include<iterator> #include<iostream> #include<algorithm> using namespace std; int main() { /* =================================== */ set< int >eg1; //插入 eg1.insert(1); eg1.insert(100); eg1.insert(5); eg1.insert(1); //元素1因为已经存在所以set中不会再次插入1 eg1.insert(10); eg1.insert(9); //遍历set,可以发现元素是有序的 set< int >::iterator set_iter=eg1.begin(); cout<< "Set named eg1:" <<endl; for (;set_iter!=eg1.end();set_iter++) cout<<*set_iter<< " " ; cout<<endl; //使用size()函数可以获得当前元素个数 cout<< "Now there are " <<eg1.size()<< " elements in the set eg1" <<endl; if (eg1.find(200)==eg1.end()) //find()函数可以查找元素是否存在 cout<< "200 isn't in the set eg1" <<endl; /* =================================== */ set< int >eg2; for ( int i=6;i<15;i++) eg2.insert(i); cout<< "Set named eg2:" <<endl; for (set_iter=eg2.begin();set_iter!=eg2.end();set_iter++) cout<<*set_iter<< " " ; cout<<endl; //获得两个set的并 set< int >eg3; cout<< "Union:" ; set_union(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set< int > >(eg3,eg3.begin())); //注意第五个参数的形式 copy(eg3.begin(),eg3.end(),ostream_iterator< int >(cout, " " )); cout<<endl; //获得两个set的交,注意进行集合操作之前接收结果的set要调用clear()函数清空一下 eg3.clear(); set_intersection(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set< int > >(eg3,eg3.begin())); cout<< "Intersection:" ; copy(eg3.begin(),eg3.end(),ostream_iterator< int >(cout, " " )); cout<<endl; //获得两个set的差 eg3.clear(); set_difference(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set< int > >(eg3,eg3.begin())); cout<< "Difference:" ; copy(eg3.begin(),eg3.end(),ostream_iterator< int >(cout, " " )); cout<<endl; //获得两个set的对称差,也就是假设两个集合分别为A和B那么对称差为AUB-A∩B eg3.clear(); set_symmetric_difference(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set< int > >(eg3,eg3.begin())); copy(eg3.begin(),eg3.end(),ostream_iterator< int >(cout, " " )); cout<<endl; return 0; } |
当然更加通用的应用方式那就是数据类型也是由用户自定义的类来替代,比较的函数自定义,甚至可以加上二级比较,比如首先按照总分数排序,对于分数相同的按照id排序
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include<iostream> #include<iterator> #include<set> #include <algorithm> #include <string> #include <list> using namespace std; struct Entity { int id; int score; string name; }; struct compare { bool operator()( const Entity& e1, const Entity& e2) const { if (e1.score<e2.score) return true ; else if (e1.score==e2.score) if (e1.id<e2.id) return true ; return false ; } }; int main() { set<Entity,compare>s_test; Entity a,b,c; a.id=123;a.score=90;a.name= "a" ; b.id=121;b.score=85;b.name= "b" ; c.id=130;c.score=85;c.name= "c" ; s_test.insert(a);s_test.insert(b);s_test.insert(c); set<Entity,compare>::iterator itr; cout<< "Score List(ordered by score):\n" ; for (itr=s_test.begin();itr!=s_test.end();itr++) cout<<itr->id<< "---" <<itr->name<< "---" <<itr->score<<endl; return 0; } |
8 set STL 源码 转自:
http://www.cnblogs.com/hustyangli/articles/1286302.html
参考:
http://www.cnblogs.com/hustyangli/articles/1286302.html
http://apps.hi.baidu.com/share/detail/16186741
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述