【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap

set

  1. 所有的元素都会根据元素的键值自动被排序。set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值。set不允许两个元素有相同的键值。

  2. 不可以通过set的迭代器改变set的元素值。因为set元素值就是其键值,关系到set元素的排列规则。如果任意改变set元素值,会严重破坏set组织。set源码中,set<T>::iterator被定义为底层RB-tree的const_iterator,杜绝写入操作。换句话,set iterators是一种constant iterators。

  3. set拥有与list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后依然有效。当然,被删除的那个元素的迭代器必然是个例外。

  4. STL set以RB-tree为底层机制,set的操作几乎都是转调用RB-tree的函数而已。

set测试代码:

  
  #include<set>
  #include<iostream>
  using namespace std;
  
  int main(){
      int ia[] = { 5, 3, 4, 1, 6, 2 };
      set<int> iset(begin(ia), end(ia));
  
      cout << "size=" << iset.size() << endl; //size=6
      cout << "3 count=" << iset.count(3) << endl;//3 count=1
  
      iset.insert(3);
      cout << "size=" << iset.size() << endl;//size=6
      cout << "3 count=" << iset.count(3) << endl;//3 count=1
  
      iset.insert(7);
      cout << "size=" << iset.size() << endl;//size=7
      cout << "3 count=" << iset.count(3) << endl;//3 count=1
  
      iset.erase(1);
      cout << "size=" << iset.size() << endl;//size=6
      cout << "1 count=" << iset.count(1) << endl;//1 count=0
  
      set<int>::iterator it;
      for (it = iset.begin(); it != iset.end(); ++it)
          cout << *it << " "; //2 3 4 5 6 7
      cout << endl;
  
      it = find(iset.begin(), iset.end(), 3);
      if (it != iset.end())
          cout << "3 found" << endl;//3 found
  
      it = find(iset.begin(), iset.end(), 1);
      if (it == iset.end())
          cout << "1 not found" << endl;//1 not found
  
      system("pause");
      return 0;
  }

map

  1. map的特性是,所有元素都会根据元素的键值自动被排序。map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一元素被视为键值,第二元素被视为实值。map不允许两个元素拥有相同的键值。下面是<stl_pair.h>中pair定义:

      
      template<class T1,class T2>
      struct pair{
          typedef T1 first_type;
          typedef T2 second_type;
          T1 first;
          T2 second;
          pair():first(T1()),second(T2()) {}
          pair(const T1& a,const T2& b):first(a),second(b) {}
      }

  2. 不能通过map的迭代器改变map的键值,但通过map的迭代器能改变map的实值。因此map的iterators既不是一种const iterators,也不是一种mutable iterators。

  3. map拥有和list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后都依然有效。当然,被删除的那个元素的迭代器必然是个例外。

  4. 由于RB-tree是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的STL map即以RB-tree为底层机制。又由于map所开放的各种操作接口,RB-tree也都提供了,所以几乎所有的map操作行为,都只是转调用RB-tree的操作行为而已。

  #include<map>
  #include<iostream>
  #include<string>
  using namespace std;
  
  int main()
  {
      map<string, int> simap;            //以string为键值,以int为实值
      simap[string("jjhou")] = 1;        //第一对内容是("jjhou",1)
      simap[string("jerry")] = 2;        //第一对内容是("jerry",2)
      simap[string("jason")] = 3;        //第一对内容是("jason",3)
      simap[string("jimmy")] = 4;        //第一对内容是("jimmy",4)
  
      pair<string, int> value(string("david"), 5);
      simap.insert(value);
  
      map<string, int>::iterator simap_iter = simap.begin();
      for (; simap_iter != simap.end(); ++simap_iter)
          cout << simap_iter->first << ' ' << simap_iter->second << endl;
                                                                  //david 5   //按键值排序
                                                                  //jason 3
                                                                  //jerry 2
                                                                  //jimmy 4
                                                                  //jjhou 1
  
      int number = simap[string("jjhou")];
      cout << number << endl;                                     //1
  
      map<string, int>::iterator ite1;
  
      //面对关联式容器,应使用其所提供的find函数来搜寻元素,会比STL算法find()更有效率。因为STL find()只是循序搜索
      ite1 = simap.find(string("mchen"));
      if (ite1 == simap.end())
          cout << "mchen not found" << endl;                      //mchen not found
  
      ite1 = simap.find(string("jerry"));
      if (ite1 != simap.end())
          cout << "jerry found" << endl;                         //jerry found
  
      ite1->second = 9;
      int number2 = simap[string("jerry")];
      cout << number2 << endl;                                   //9
  }

multiset

multiset的特性以及用法和set完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。

  
  #include<set>
  #include<iostream>
  #include<vector>
  using namespace std;
  
  int main() {
      vector<int> a = { 5, 3, 4, 1, 6, 2 };
      multiset<int> iset(a.begin(),a.end());
  
      cout << "size=" << iset.size() << endl; //size=6
      cout << "3 count=" << iset.count(3) << endl;//3 count=1
  
      iset.insert(3); //和set区别的地方
      cout << "size=" << iset.size() << endl;//size=7
      cout << "3 count=" << iset.count(3) << endl;//3 count=2
  
      iset.insert(7);
      cout << "size=" << iset.size() << endl;//size=8
      cout << "3 count=" << iset.count(3) << endl;//3 count=2
  
      iset.erase(1);
      cout << "size=" << iset.size() << endl;//size=7
      cout << "1 count=" << iset.count(1) << endl;//1 count=0
  
      set<int>::iterator it;
      for (it = iset.begin(); it != iset.end(); ++it)
          cout << *it << " "; //2 3 3 4 5 6 7
      cout << endl;
  
      it = find(iset.begin(), iset.end(), 3);
      if (it != iset.end())
          cout << "3 found" << endl;//3 found
  
      it = find(iset.begin(), iset.end(), 1);
      if (it == iset.end())
          cout << "1 not found" << endl;//1 not found
  
      system("pause");
      return 0;
  }
  

multimap

multimap的特性以及用法与map完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。

  
  #include<map>
  #include<string>
  #include<iostream>
  using namespace std;
  
  int main(){
      multimap<string, int> mp;//multimap没有下标操作
      mp.insert(pair<string, int>("Jack", 1));
      mp.insert(pair<string, int>("John", 2));
      mp.insert(pair<string, int>("Lily", 3));
      mp.insert(pair<string, int>("Kate", 4));//按键值字典序排序
      mp.insert(pair<string, int>("Tom", 5));              //Jack 1
      mp.insert(pair<string, int>("John", 8));            //John 2   
                                                          //John 8   
      map<string, int>::iterator it;                      //Kate 4
      for (it = mp.begin(); it != mp.end(); ++it)         //Lily 3
          cout << it->first << " " << it->second << endl; //Tom 5
  
      it = mp.find("John");
      if (it != mp.end())
          cout << "John found" << endl; //John found
      it->second = 8;
  
      it = mp.find("John");
      cout << it->second << endl;//8
  
      system("pause");
      return 0;
  }

猜你喜欢

转载自blog.csdn.net/u012940886/article/details/80708284