• STL关联式容器之setmap ----以STL源码为例


    关联式容器的特征:所用元素都会根据元素的键值自动被排序。

    set

    • STL 中的关联式容器低层数据结构为红黑树,其功能都是调用低层数据结构中提供的相应接口。
    • set元的元素不会像map那样同时拥有键(key)和值(value)。
    • set元素的键就是值,值就是键,并不允许两个元素有相同的键。
    • multiset允许相同键值存在。
    • 因为set元素的键和值相等,所以不允许对set元素的值进行修改。(数据结构会根据key对元素进行排序,对value的更改会改变树中元素的排列顺序)。
    • set容器提供的迭代器为 const iterator;
      set类的声明:
    template <class _Key, class _Compare, class _Alloc>
    class set;
    

    set类含三个模板参数,键类型_Key,键比较方法_Compare,分配器类型_Alloc;平时经常用到的是第一个模板参数:键类型_Key,如:

    set<int> iset={1,2,3,4,5};
    

    另外两个模板参数在特殊的应用场景上会发挥作用。_Compare模板参数可以指定容器中元素的比较方法,根据容器存放元素的大小,可修改内存分配策略_Alloc。这两个参数都可已通过设置set的构造函数参数来进行指定:

      explicit set(const _Compare& __comp,
                   const allocator_type& __a = allocator_type())
        : _M_t(__comp, __a) {}
    

    如果set未指定后两个模板参数,则会调用默认版本:

    template <class _Key, class _Compare __STL_DEPENDENT_DEFAULT_TMPL(less<_Key>),
              class _Alloc = __STL_DEFAULT_ALLOCATOR(_Key) >
    class set;
    

    map

    • map的每个元素都是一个pair<_key,_value>,同时拥有键值对。
    • map不允许两个元素的键相同。
    • map可以通过迭代器修改元素的值,但不能修改键(会改变元素排列)。map iterator 是一种介于const iterator 和mutable iterator 之间的迭代器。
    template <class _Key, class _Tp, class _Compare, class _Alloc>
    class map ;
    

    map类有四个类模板参数,分别是:键类型_Key,值类型_Tp,键比较方法_Compare,分配器类型_Alloc;平时经常用到的是前两个模板参数:键类型_Key和值类型_Tp,如:

    #include<iostream>
    #include<map>
    
    using namespace std;
    
    int main(){
    	map<int,string> ismap={{1,"Hello"},{2,"World"}};
    	cout<<ismap[1]<<endl;        //Hello
    	cout<<ismap[2]<<endl;        //World
    
    	return 0;
    }
    

    若不指定后两个参数,则会使用默认模板参数:

    template <class _Key, class _Tp, 
              class _Compare __STL_DEPENDENT_DEFAULT_TMPL(less<_Key>),
              class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
    class map;
    

    map的按照键映射值是通过[]运算符来进行的:

      _Tp& operator[](const key_type& __k) {
        iterator __i = lower_bound(__k);
        // __i->first is greater than or equivalent to __k.
        // insert那句,根据键值和实值取出一个元素,由于实值未知,所以产生一个与实值
        // 类型相同的暂时对象替代->value_type(__k,_Tp()),然后将这个元素插入到map里面
        // 此时,__i指向插入之后的新位置的迭代器,然后在返回实值。
        if (__i == end() || key_comp()(__k, (*__i).first))
          __i = insert(__i, value_type(__k, _Tp()));
        return (*__i).second;
      }
    

    该函数首先对键__k进行搜索,若没有找到,则在搜索结束位置插入新的节点。函数返回的是键所对应值的引用,因此,可以对其进行赋值。

    multiset和multimap

    multiset和multimap的用法和set,map的用法相同,不过它们允许重复的键。对应到源代码上就是,multi版本的插入操作调用红黑树的insert_equal接口,而普通版本则调用insert_unique接口。以multiset为例:
    set版本

      pair<iterator,bool> insert(const value_type& __x) { 
        pair<typename _Rep_type::iterator, bool> __p = _M_t.insert_unique(__x); 
        return pair<iterator, bool>(__p.first, __p.second);
      }
    

    multiset版本

      iterator insert(const value_type& __x) { 
        return _M_t.insert_equal(__x);
      }
    

    小结

    • map和set是常用的关系型容器,两者内部都使用红黑树作为低层数据结构。类提供的接口都调用红黑树提供的相应接口。是对红黑树类的封装(适配)。
    • set和map中的元素都是自动排序的。
    • set的元素是键(等于值)。map的元素是键值对(key-value pair),可以提供键到值的映射功能。
    • set中的值(键)不能被修改,map中元素的值可以被修改,而键不能被修改。
  • 相关阅读:
    《对不队》团队项目软件系统设计改进
    《对不队》团队作业五——项目需求改进
    《对不队》团队作业4—基于原型的团队项目需求调研与分析
    《对不队》第三次作业—团队项目的原型设计与开发
    《对不队团队》第二次作业:学术管理系统开题报告
    《对不队团队》第一次作业:团队亮相
    LINUX命令-shell基础命令
    Python实战-数据结构
    Python实战-函数
    lambda
  • 原文地址:https://www.cnblogs.com/SupremeGIS-Developer/p/11924179.html
Copyright © 2020-2023  润新知