您的位置:首页 > 其它

[置顶] STL——set && map的使用

2018-04-04 19:56 393 查看
set  set实现了红黑树(RBTree)平衡二叉搜索树的数据结构,模板参数为key,相当于是K模型的集合。  在插入元素时会自动调整二叉树,使其尽量保持平衡,以至于在树中进行搜索时,能够达到logn的搜索效率,对于重复插入的值,会插入失败。
使用时,记得加上头文件哦!
#include <set>
1 元素的插入 set.insert()
void test_set()
{
set<int> s1;
s1.insert(10);
s1.insert(15);
s1.insert(13);
s1.insert(19);
s1.insert(16);
s1.insert(15);
set<int>::iteratorit1; //定义迭代器,方便访问数据
it1 = s1.begin();    //s1.begin返回第一个元素的迭代器(即树中最左端元素)
while(it1 != s1.end()) //s1.end返回最后一个元素的下一个迭代器
{
cout << *it1 <<" ";
it1++;
}
cout << endl;
}
输出结果为:



    由于set底层为RBTree,所以不能有重复值的元素,在上面的代码中,尽管插入了两次15,但输出结果中只有一个,那是因为只有第一次插入成功,第二次则插入失败。
2 元素的删除 set.erase()
//erase 需要借助find()找到需要删除的数据的迭代器
it1 = s1.find(15);
s1.erase(it1);
for(it1 = s1.begin(); it1 != s1.end(); ++it1)
{
cout << *it1 <<" ";
}
cout << endl;
输出结果为:



3 元素的查找 set.find()
//find 返回的是元素的迭代器
it1 = s1.find(15);
if(it1 != s1.end())
cout << *it1 << endl;
else
cout <<"no find!" << endl;
it1 = s1.find(15);
s1.erase(it1);
it1 = s1.find(30);
if(it1 != s1.end())
cout << *it1 << endl;
else
cout <<"no find!" << endl;
输出结果为:


4 使用rbegin和rend进行反向遍历
//使用rbegin和rend进行反向遍历
set<int>::reverse_iteratorit2;//定义反向迭代器
it2 = s1.rbegin();
while(it2 != s1.rend())
{
cout << *it2 <<" ";
it2++;
}
cout << endl;
输出结果为:



由输出结果可看出,反向遍历时定义的反向迭代器,相当于在建RBTree时,让较大的为左孩子,较小的为右孩子。
5 一个例题,熟悉set的其他接口找出两组字符串的相同和不同的
void test_set1()
{
set<string> s1;
set<string> s2;
s1.insert("set");
s1.insert("sort");
s1.insert("string");
s2.insert("set");
s2.insert("sort");
s2.insert("string");
s2.insert("map");
s2.insert("test");
set<string> diffs;//不同
set<string> sames;//相同
set<string>::iteratorit1 = s1.begin();
set<string>::iteratorit2 = s2.begin();
while(it1 != s1.end() && it2 != s2.end())
{
if(*it1 < *it2)
{
diffs.insert(*it1);
it1++;
}
elseif(*it1 > *it2)
{
diffs.insert(*it2);
it2++;
}
else
{
sames.insert(*it1);
it1++;
it2++;
}
}
if(it1 != s1.end())
{
while(it1 != s1.end())
{
diffs.insert(*it1);
it1++;
}
}
else
{
while(it2 != s2.end())
{
diffs.insert(*it2);
it2++;
}
}
cout <<"different:";
for(it1 = diffs.begin(); it1 != diffs.end(); ++it1)
{
cout << *it1 <<" ";
}
cout << endl <<"same:";
for(it2 = sames.begin(); it2 != sames.end(); ++it2)
{
cout << *it2 <<" ";
}
cout << endl;
}
输出结果:



map
  map和set原理相同,只不过map的模板参数有两个,分别为key和value,是KV模型的映射集合。  在STL库中,将这两个参数放到了一个名为pair的结构体中,key和value分别对应的是pair结构体中的first和second。
使用map前也要记得加上它的头文件呦!
#include<map>
1 元素的插入 map.insert()
//insert
map<string,string> m1;
m1.insert(pair<string,string>("insert","插入"));
m1.insert(pair<string,string>("sort","排序"));
m1.insert(pair<string,string>("return","返回"));
m1.insert(pair<string,string>("erase","删除"));
map<string,string>::iteratorit1;
for(it1 = m1.begin(); it1 != m1.end(); ++it1)
{
cout << it1->first <<":" << it1->second << endl;
}
输出结果为:



map底层是RETree,在排序时是依据key进行的。
2 元素的删除 map.erase()
//erase
it1 = m1.find("erase");
m1.erase(it1);
for(it1 = m1.begin(); it1 != m1.end(); ++it1)
{
cout << it1->first <<":" << it1->second << endl;
}
输出结果为:



3 元素的查找 map.find()
//find 在使用find时可以看到,参数只有一个key value
//因为map中每一个节点的内容是一个pair的结构体,只根据一个参数便可以找到这个节点
it1 = m1.find("erase");
cout << it1->second << endl;
输出结果为:



4 元素的修改 借助find进行
//借助find对元素的修改
//修改时应注意,只能对第二个参数mapped value进行修改,否则会破坏RBTree
it1 = m1.find("erase");
it1->second ="erase";
for(it1 = m1.begin(); it1 != m1.end(); ++it1)
{
cout << it1->first <<":" << it1->second << endl;
}
输出结果为:



5 使用map统计单词出现的次数(1)统计单词出现的次数,map的两个参数类型应该为map<string,size_t>;(2)insert的返回值是pair<iterator,bool>,其中bool表示是否插入成功;
void test_mapcount()
{
map<string,size_t> CountMap;
stringstr[] = { "insert","sort","return" ,"insert"};
pair<map<string,size_t>::iterator,bool> ret;
for(size_ti = 0; i < sizeof(str) /sizeof(str[0]); ++i)
{
ret = CountMap.insert(make_pair(str[i], 1));
if(ret.second == false)
{
//ret.first->second++;
CountMap[str[i]]++;
}
}
map<string,size_t>::iteratorit;
for(it = CountMap.begin(); it != CountMap.end(); ++it)
{
cout << it->first <<":" << it->second << endl;
}
}
输出结果为:


6 解析operator[]  首先我们观察一下insert的返回值:
pair<iterator,bool> insert (const value_type& val);
可以看到,insert的返回值是pair<iterator,bool>,所以它返回的是插入的这一点的迭代器,和是否插入成功的bool。    在了解了insert的返回值后,步入正题,开始探究operator[]的实现:
mapped_type&operator[] (constkey_type& k)
{
return(*((this->insert(make_pair(k, mapped_type()))).first)).second;
}
一步步分析:



吼吼!这样就明白为什么可以 CountMap[str[i]]++来统计次数啦!其实,operator[]的使用非常广泛,可以进行创建和修改,来看一下:
void test()
{
map<string,string> m;
map<string,string>::iteratorit;
m["string"];
m["string"] = "字符串";
m["return"] = "返回";
}
调试过程中m为:


multiset && multimap1 multiset和set类似,没有单独需要包的头文件,实现的是可重复的set;2 multimap和map类似,也没有单独需要包的头文件,仍为:#include <map>,实现的是可重复的map。验证一下他们的使用:
void test_multiset()
{
multiset<int> ms;
ms.insert(5);
ms.insert(7);
ms.insert(6);
ms.insert(5);
multiset<int>::iteratorit;
for(it = ms.begin(); it != ms.end(); ++it)
{
cout << *it <<" ";
}
cout << endl;
}

void test_multimap()
{
multimap<string,string> mm;
mm.insert(make_pair("string","字符串"));
mm.insert(make_pair("left","左边"));
mm.insert(make_pair("left","剩余"));
mm.insert(make_pair("test","测试"));
multimap<string,string>::iteratorit;
for(it = mm.begin(); it != mm.end(); ++it)
{
cout << it->first <<":"<<it->second<<endl;
}
}
输出结果为:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: