STL——set & map的使用

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 && multimap
1 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;
      }
}
输出结果为:






猜你喜欢

转载自blog.csdn.net/weixin_39294633/article/details/79821603