stl set,map ,hash_map学习

1. map功能:

  1. 自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
  2. 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
  3. 快速插入Key - Value 记录。
  4. 快速删除记录
  5. 根据Key 修改value记录。
  6. 遍历所有记录。

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

 
 
 
posted @   wtx  阅读(4297)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 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的设计模式综述
点击右上角即可分享
微信分享提示