A brief look at STL associative containers, primarily map, multimap, set, multiset, and unordered_map. The first four are implemented using a red-black tree with O(log n) lookup, while unordered_map — as the name suggests — is an unordered container backed by a hash table with O(1) lookup.

set, multiset, map, multimap

set stores a sorted collection of unique elements — duplicates are not allowed. It is backed by a red-black tree. multiset works the same way but allows duplicate elements.

map is an associative table that can use any type as the key, with no duplicate keys. Its implementation mirrors set, both built on a red-black tree. multimap allows duplicate keys.

template<typename _Key, typename _Compare = std::less<_Key>,typename _Alloc = std::allocator<_Key> >
class set 
public:
    typedef _Key     key_type;
    typedef _Key     value_type;    // differs from map
    typedef _Compare key_compare;
    typedef _Compare value_compare; 
    typedef _Alloc   allocator_type;

private:
    typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Key>::other _Key_alloc_type;
    typedef _Rb_tree<key_type, value_type, _Identity<value_type>, key_compare, _Key_alloc_type> _Rep_type;
    
    _Rep_type _M_t;  // Red-black tree representing set.

    typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits;

#if __cplusplus > 201402L
      using node_type = typename _Rep_type::node_type;
      using insert_return_type = typename _Rep_type::insert_return_type;
#endif

map follows the same design as set, except each element is a std::pair.

template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,typename _Alloc=std::allocator<std::pair<const _Key, _Tp> > >
class map {
public:
    typedef _Key key_type;
    typedef _Tp mapped_type;
    typedef std::pair<const _Key, _Tp> value_type;      // stored as key-value pairs
    typedef _Compare key_compare;                       // RB-tree needs element comparison
    typedef _Alloc allocator_type;

private:
    /// This turns a red-black tree into a [multi]map.
    typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<value_type>::other _Pair_alloc_type;
    typedef _Rb_tree<key_type, value_type, _Select1st<value_type>, key_compare, _Pair_alloc_type> _Rep_type;

    /// The actual tree structure.
    _Rep_type _M_t;     // underlying RB-tree

    typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits;

public:
    // operator[] overload
    mapped_type& operator[](const key_type& __k) {
	    // concept requirements
	    __glibcxx_function_requires(_DefaultConstructibleConcept<mapped_type>)
        iterator __i = lower_bound(__k);
	    // __i->first is greater than or equivalent to __k.
	    if (__i == end() || key_comp()(__k, (*__i).first))
#if __cplusplus >= 201103L
	        __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, std::tuple<const key_type&>(__k),
std::tuple<>());
#else
	        __i = insert(__i, value_type(__k, mapped_type()));
#endif
	    return (*__i).second;
    }
}

Further implementation details are omitted; once you understand red-black trees, the rest follows easily.

unordered_map

Unlike map, unordered_map is backed by a hash table — understand hashing, and you’ll understand unordered_map.

template<class _Key, class _Tp,class _Hash = hash<_Key>,class _Pred = std::equal_to<_Key>,class _Alloc=std::allocator<std::pair<const _Key, _Tp> > >
class unordered_map {
    typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc>  _Hashtable;
    _Hashtable _M_h;    // underlying hash table implementation

public:
    // typedefs:
    //@{
    /// Public typedefs.
    typedef typename _Hashtable::key_type	key_type;
    typedef typename _Hashtable::value_type	value_type;
    typedef typename _Hashtable::mapped_type	mapped_type;
    typedef typename _Hashtable::hasher	hasher;
    typedef typename _Hashtable::key_equal	key_equal;
    typedef typename _Hashtable::allocator_type allocator_type;
    //@}

#if __cplusplus > 201402L
      using node_type = typename _Hashtable::node_type;
      using insert_return_type = typename _Hashtable::insert_return_type;
#endif