zoukankan      html  css  js  c++  java
  • unorder_set<typename T> 学习

    转自http://blog.csdn.net/mmzsyx/article/details/8240071

    散列容器(hash container):
     通常比二叉树的存储方式可以提供更高的访问效率.
    #include <boost/unordered_set.hpp>
    #include <boost/unordered_map.hpp>
    using namespace boost;
    散列集合简介:
     unordered库提供两个散列集合类unordered_set和unordered_multiset,STLport也提供hash_set和hash_multiset,它们的接口,用法与stl里的标准关联容器set/multiset相同,只是内部使用散列表代替了二叉树实现,因此查找复杂度由数降为常数。
    unordered_set/unordered_multiset简要声明:
    template<class Key, class Hash = boost::hash<Key>,
     class Pred = std::equal_to<Key>,
     class Alloc = std::allocator<Key>>
    class unordered_set;

    template<class Key, class Hash = boost::hash<Key>,
     class Pred = std::equal_to<Key>,
     class Alloc = std::allocator<Key>>
    class unordered_multiset;
    与std::set相比,unorder_set的模板增加了一个计算散列值的模板类型参数,通常是boost::hash,最好不要去改变它,另外比较谓词参数使用std::equal_to<>,而不是set中的less<>,这是因为散列容器不需要保持有序。

    散列集合的用法:
     注意散列容器的无序性,不能再散列容器上使用binary_search,lower_bound和upper_bound这样用于已序区间的算法,散列容器自身也不提供这样的成员函数。
    示范:程序定义了一个模板函数hash_func(),用以操作hash_set/unordered_set,两者的表现是完全一样的,首先使用boost::assign初始化散列集合,以迭代器遍历输出,然后用size()显示容器大小,用clear()清空集合,再用insert()插入两个元素,用find()查找元素,最后用erase()删除一个元素,这些都是标准容器的标准操作。

    #include <iostream>
    #include <hash_set>
    #include <boost/unordered_set.hpp>
    #include <boost/assign/list_of.hpp>
    using namespace boost;
    using namespace std;
    template<typename T>
    void hash_func()
    {
     using namespace boost::assign;
     T s = (list_of(1), 2, 3, 4, 5);   //初始化数据
     for (T::iterator p = s.begin(); p != s.end(); ++p) //使用迭代器遍历集合
     { cout<< *p<<" "; }
     cout<<endl;
     cout<<s.size()<<endl;
     s.clear();
     cout<<s.empty()<<endl;
     s.insert(8);
     s.insert(45);
     cout<<s.size()<<endl;
     cout<<*s.find(8)<<endl;
     s.erase(45);
    }

    int main()
    {
     hash_func<unordered_set<int>>();
     system("pause");
     return 0;
    }

    散列映射简介:
     unordered库提供两个散列映射类undorderd_map和unordered_multimap,它们的接口,用法与stl里的标准关联容器map/multimap相同,只是内部使用散列表代替了二叉树,模板参数多了散列计算函数,比较谓词使用equal_to<>。
     unordered_map和unordered_multimap的简要声明:
    template<class Key, class Mapped,
     class Hash = boost::hash<Key>,
     class Pred = std::equal_to<Key>,
     class Alloc = std::allocator<Key>>
    class unordered_map;

    template<class Key, class Mapped,
     class Hash = boost::hash<Key>,
     class Pred = std::equal_to<Key>,
     class Alloc = std::allocator<Key>>
    class unordered_multimap;
    散列映射的用法:
     unordered_map/unordered_multimap属于关联式容器,采用std::pair保存key-value形式的数据,可以理解一个关联数组,提供operator[]重载,用法与标准容器map相同.
     unordered_multimap允许有重复的key-value映射,因此不提供operator[].
    示范:
    #include <iostream>
    #include <hash_map>
    #include <boost/unordered_map.hpp>
    #include <boost/assign/list_of.hpp>
    #include <boost/typeof/typeof.hpp>
    using namespace boost;
    using namespace std;
    using namespace stdext; 
    int main()
    {
     using namespace boost::assign;
     //使用assign初始化
     unordered_map<int, string> um = map_list_of(1, "one")(2, "two")(3, "three");
     um.insert(make_pair(10, "ten"));
     cout<<um[10]<<endl;
     um[11] = "eleven";
     um[15] = "fifteen";
     for (BOOST_AUTO(p, um.begin()); p != um.end(); ++p)
      cout<<p->first<<"-"<<p->second<<",";
     cout<<endl;
     um.erase(11);
     cout<<um.size()<<endl;
     hash_map<int, string> hm = map_list_of(4, "four")(5, "five")(6, "six");
     for (BOOST_AUTO(p, hmbegin()); p != hm.end(); ++p)
      cout<<p->first<<"-"<<p->second<<",";
     cout<<endl;
     system("pause");
     return 0;
    }

    性能比较:
    示范:程序使用boost随机库random()向容器插入10000个1到100之间的整数,然后执行count和find操作;
    #include <iostream>
    #include <typeinfo>
    #include <hash_map>
    #include <set>
    #include <boost/unordered_set.hpp>
    #include <boost/assign/list_of.hpp>
    #include <boost/typeof/typeof.hpp>
    #include <boost/random.hpp>
    #include <boostProgress.hpp>
    using namespace boost;
    using namespace std;
    using namespace stdext;

    template<typename T>
    void fill_set(T &c)
    {
     variate_generator<mt19937, uniform_int<>> gen(mt19937(), uniform_int<>(0, 100));
     for (int i = 0; i < 10000; ++i)//插入一万个整数
      c.insert(gen());
    }
    template<typename T>
    void test_perform()
    {
     T c;
     cout<<typeid(c).name()<<endl;
     {
      boost::progress_timer t;
      fill_set(c);
     }
     {
      boost::progress_timer t;
      c.count(10);
     }
     {
      boost::progress_timer t;
      c.find(20);
     }
    }

    int main()
    {
     test_perform<multiset<int>>();
     //test_perform<hash_multiset<int>>();
     test_perform<unordered_multiset<int>>();
     system("pause");
     return 0;
    }

    高级议题:
    内部数据结构:
     unordered库使用“桶(bucket)”来存储元素,散列值相同的元素被放入同一个桶中,当前散列容器的桶的数量可以用成员函数bucket_count()来获得,bucket_size()返回桶中的元素数量,例如:
    unordered_set<int> us = (list_of(1), 2, 3, 4);
    cout<< us.bucket_count()<<endl;
    for(int i = 0; i < us.bucket_count(); ++i)//访问每个桶
    {cout<<us.bucket_size(i)<<",";}
     当散列容器中有大量数据时,桶中的元素数量也会增多,会造成访问冲突。为了提高散列容器的性能,unordered库会在插入元素时自动增加桶的数量,用户不能直接指定桶的数量,但可以在构造函数或者rehash()函数指定最小的桶的数量。例如:
    unordered_set<int> us(100);//使用100个桶存储数据
    us.rehash(200);//使用200个桶
     c++0x RT1草案还规定有一个函数max_load_factor(),它可以获取或设定散列容器的最大负载因子,即桶中元素的最大平均数量,通常最大负载因子都是1,用户不应当去改变它,过大或过小都没有意义。

    支持自定义类型:
     unordered库支持c++内建类型和大多数标准库容器,但不支持用户自定义的类型,因为它无法计算自定义类型的散列值。
     如果要使unordered支持自定义类型,需要定制类模板的第二个和第三个参数,也就是供散列函数和相等比较谓词。
     相等比较谓词,unordered库默认使用std::equal_to,这是一个标准库中的函数对象,它使用operator==,只有自定义类实现了这个操作符就可以了,不必再特意编写一个函数对象,如果需要用一个特别的相等判断规则,那么可以额外写函数对象,传递给unordered容器。
     散列函数则是必须要实现的,这也是为什么它被放在模板参数列表前面的原因,我们需要使用boost.hash库来计算自定义类型的散列值,组简单的使用方法是编写一个hash_value()函数,创建一个hash函数对象,然后使用它的operator()返回散列值。
    下面的代码定义了一个类demo_class,它实现了operator==和散列函数,可以被unordered所容纳:
    #include <iostream>
    #include <typeinfo>
    #include <hash_map>
    #include <set>
    #include <boost/unordered_set.hpp>
    #include <boost/assign/list_of.hpp>
    #include <boost/typeof/typeof.hpp>
    #include <boost/random.hpp>
    #include <boost/Progress.hpp>
    #include <boost/functional/hash.hpp>
    using namespace boost;
    using namespace std;
    using namespace stdext;
    using namespace boost::assign;
    struct demo_class
    {
     int a;
     friend bool operator==(const demo_class& l, const demo_class& r)
     {  return l.a == r.a; }
    };
    size_t hash_value(demo_class & s)
    { return boost::hash<int>()(s.a);}

    int main()
    {
     unordered_set<demo_class> us;
     demo_class a1;
     a1.a =100;
     cout<<hash_value(a1)<<endl;
     demo_class a2;
     a2.a =100;
     cout<<hash_value(a2)<<endl;

     system("pause");
     return 0;
    }
    与TR1的差异:
     boost.unordered基本上依据c++0x标准草案来实现,但它有个小的”扩充“,增加了比较操作符operator==和operator !=;注意:这两个操作符不属于c++0x标准,如果将来程序要切换到新标准可能会遇到不可用移植的问题。

  • 相关阅读:
    jsp mysql 配置线程池
    服务端 模拟 检测 攻击。。乱写
    硕思闪客精灵 7.2 破解版
    unity UnityAwe 插件
    smartfoxserver 2x 解决 Math NAN
    unity 断点下载
    java 监听文件目录修改
    wind7 64 setup appjs
    sfs2x 修改jvm 内存
    unity ngui 解决图层问题
  • 原文地址:https://www.cnblogs.com/qingcheng/p/3402722.html
Copyright © 2011-2022 走看看