• STL hash table, Unordered Contains


    STL hash table, Unordered Contain

     

    C++11加入使用hash table实现的Unordered Containers。容器中元素是不排序的,同时我们也不能指定某个元素的位置。

    头文件:#include <unordered_set>   unordered_set; unordered_multiset;

              #include <unordered_map> unordered_map; unordered_multimap;

    操作基本类似于关联容器,只是底层使用hash table。主要不同是理解bucket的概念。

    namespace std {

        template <typename T,

                       typaname Hash = hash<T>,

                        typename EqPred = equal_to<T>,

                        typename Allocator = allocator<T> >

        class unordered_set;

        template <typename Key, typename T,

                      typanem Hash = hash<T>,

                      typename EqPred = equal_to<T>,

                      typanema Allocator = allocator<pair<const Key, T> > >

    class unordered_ma;
    }

    注意点:

    (1) hash函数为hash<T>

    (2) 比较准则 equal_to<T>

    1.特点

    标准没有指定实现,vs和g++都使用开链法实现。

    指定迭代器至少为forward_iterator,但是具体实现一般都是forward_iterator。

    插入,删除,查找元素保证分摊的常数时间。rehashing可能发生,这是一个线性复杂度的操作。

    相对于普通关联容器的不利:

    (1) 不提供<, >, <=,>=去排序元素,since c++11提供了==, !=。

    (2)不提供lower_bound(), upper_bound()

    (3) 不提供反向迭代器,forward_iterator

    (4)不能直接访问元素

    (5) 可以通过iterator访问元素,key值是const。

    (6) 可以指定min 桶数。

    (7) 可以提供自定义的hash function。

    (8)可以指定查找元素时的相等准则。重载operator=。

    (9) 可以指定max 负载因子,当超过时可以自动重排。

    (9) 可以强制rehashing。

    rehashing发生的时机:只有在insert(), rehash(), reserve(), clear()之后才可能。

    这保证了erase()从来都不会使iterator,reference,和指针失效。

    因此,当你删除很多元素是,桶的大小不会改变。但是当你insert()一个元素时,桶的大小可能压缩(rehash)。

    相等key是相邻的,rehashing时保证key的相对顺序不变。

    2.构造,复制,赋值

    unordered c([bnum], [hf], [cmp]);     //桶数目,hash function, 比较谓词都是可选

    unordered c(beg, end, [bnum][hf][cmp]);

    unordered c = initlist;

    unordered c(initlist);

    复制和移动复制

    c.~Unord();

    主要的特点是可以指定:bucket num,hash function, cmp

    3.容器内部布局的操作

    c.hash_function()

    c.key_eq()

    c.bucket(val): 返回val所在的桶的索引

    c.bucket_count():返回桶的数目,size()返回所有元素的数目。

    c.size():返回元素的数目

    c.bucket_size(buckidx): 返回桶buckidx的元素数目

    c.[c]begin(buckdx):返回桶buckdx的第一个元素forward iter

    c.[c]end(buckdx):返回桶buckdx的最后一个元素之后位置

    c.max_bucket_count(): 最大桶的数目

    c.load_factor():返回当前的负载因子,0.7..0.8之间速度和内存消耗是最平均的。

    c.max_load_factor:返回当前最大负载因此,<=1。

    c.max_load_factor(val):设置最大负载因子为val,当当前的负载因子 > val时rehashing。若是比较关心速度,可以设置这个。

    c.rehashi(bnum); 再散列容器,桶的大小至少为bnum。但是还要考虑到此时的负载因子, 可以存的元素数量为 load_factor * bunm <= bnum; 当前元素数量可能大于此值,可能会进一步的再散列。

    c.reserve(num);再散列容器,元素数量至少为num。已考虑了负载因子,能够至少存num个元素而不会再散列。桶的数量为num / load_factor。保证可以存下num元素而不会再散列。

    4. 定义自己的hash function

    hash function映射元素的值到一个指定的桶,自定义hash function只需映射不同元素值相等的分布在[0, size_t)。

    #include <functional>

    class  customer

    {

         …
    }

    class CustomerHash

    {

          public:

                std::size_t operator() (const Customer &c) const

               {

                         return…
               }

    }

    std::unordered_set<Customer, CustomerHash> custset;

    也可以使用函数:

    std::size_t customer_hash_func(const Customer &c)

    {

         return …
    }

    std::unordered_set<Customer, std:size_t(*)(const Customer&)>

    custset(20, customer_hash_func);

    对于hash_val的选择:

    可以使用boost的hash_combine()。

    5.定义自己的Equivalence Criterion

    可以作为我们查找值的相等准则,默认使用equal_to()使用operator==比较元素。

    可以使用普通函数或者函数对象。

    注意:带着非默认相等谓词的unordered 容器通常也需要一个非默认的hash function。

    6. 查找

    主要在快速查找时用

    c.count(val);

    c.find(val);

    c.equal_range(val);

     

  • 相关阅读:
    一些小姿势
    <学习笔记>《具体数学》
    【react】报错Need at least a key or a value or a label (only for OptGroup) for [object Object]
    Calibration Checkerboard Collection
    华为云如何建表并创建作业定时调度抽取数据
    HIVE SQL教程
    postgresql 教程
    PC机启用了fiddler代理,在手机或其它机器上连接该代理,无法抓包
    Unity3d的Scroll View组件不能滑动到底的解决方式
    Unity3d让GridLayoutGroup按照子物体的数量自动调整宽高
  • 原文地址:https://www.cnblogs.com/hancm/p/3903181.html
Copyright © 2020-2023  润新知