1.散列容器(hash container)

   散列容器通常比二叉树的存储方式可以提供更高的访问效率.

 #include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
using namespace boost;

2.散列集合简介

  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<>,这是因为散列容器不需要保持有序。

3.散列集合的用法

  注意散列容器的无序性,不能再散列容器上使用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(), , , , ); //初始化数据
  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();
  s.insert();   cout<<s.size()<<endl;
  cout<<*s.find()<<endl;   s.erase();
} int main()
{
  hash_func<unordered_set<int>>();   system("pause");
  return ;
}

4.散列映射简介

 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;

5.散列映射的用法

 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(, "one")(, "two")(, "three");   um.insert(make_pair(, "ten"));
  cout<<um[]<<endl;   um[] = "eleven";
  um[] = "fifteen";
  for (BOOST_AUTO(p, um.begin()); p != um.end(); ++p)
    cout<<p->first<<"-"<<p->second<<",";
  cout<<endl;   um.erase();
  cout<<um.size()<<endl;   hash_map<int, string> hm = map_list_of(, "four")(, "five")(, "six");
  for (BOOST_AUTO(p, hmbegin()); p != hm.end(); ++p)
    cout<<p->first<<"-"<<p->second<<",";
  cout<<endl;   system("pause");
  return ;
}

  性能比较:

  示范:程序使用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 <boost\Progress.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<>(, ));
  for (int i = ; i < ; ++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();
  }
  {
    boost::progress_timer t;
    c.find();
  }
} int main()
{
  test_perform<multiset<int>>();
  //test_perform<hash_multiset<int>>();
  test_perform<unordered_multiset<int>>();
  system("pause");
  return ;
}

  高级议题:

  内部数据结构:
   unordered库使用“桶(bucket)”来存储元素,散列值相同的元素被放入同一个桶中,当前散列容器的桶的数量可以用成员函数bucket_count()来获得,bucket_size()返回桶中的元素数量,例如:

 unordered_set<int> us = (list_of(), , , );
cout<< us.bucket_count()<<endl;
for(int i = ; i < us.bucket_count(); ++i)//访问每个桶
{cout<<us.bucket_size(i)<<",";}

  当散列容器中有大量数据时,桶中的元素数量也会增多,会造成访问冲突。为了提高散列容器的性能,unordered库会在插入元素时自动增加桶的数量,用户不能直接指定桶的数量,但可以在构造函数或者rehash()函数指定最小的桶的数量。例如:

 unordered_set<int> us();//使用100个桶存储数据
us.rehash();//使用200个桶

  c++0x RT1草案还规定有一个函数max_load_factor(),它可以获取或设定散列容器的最大负载因子,即桶中元素的最大平均数量,通常最大负载因子都是1,用户不应当去改变它,过大或过小都没有意义。

  支持自定义类型:
     1)unordered库支持c++内建类型和大多数标准库容器,但不支持用户自定义的类型,因为它无法计算自定义类型的散列值。
     2)如果要使unordered支持自定义类型,需要定制类模板的第二个和第三个参数,也就是供散列函数和相等比较谓词。
     3)相等比较谓词,unordered库默认使用std::equal_to,这是一个标准库中的函数对象,它使用operator==,只有自定义类实现了这个操作符就可以了,不必再特意编写一个函数对象,如果需要用一个特别的相等判断规则,那么可以额外写函数对象,传递给unordered容器。
     4)散列函数则是必须要实现的,这也是为什么它被放在模板参数列表前面的原因,我们需要使用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 =;
  cout<<hash_value(a1)<<endl;   demo_class a2;
  a2.a =;
  cout<<hash_value(a2)<<endl;   system("pause");
  return ;
}

  与TR1的差异:

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

unordered容器的更多相关文章

  1. C++标准库分析总结(七)——<Hashtable、Hash_set、Hash_multiset、unordered容器设计原则>

    编译器对关联容器的实现有两个版本,上一节总结了以红黑树做为基础的实现版本,这一节总结以哈希表(hash table,散列表)为底部结构的实现版本. 一.Hashtable简单介绍 Hashtable相 ...

  2. C++主流编译器整理(编译器版本--供应商--C++11支持情况)

    C++标准   年份 C++标准                俗称   备注 2011 ISO/IEC 14882:2011     C++11  第三个C++标准 2007 ISO/IEC TR ...

  3. unorder_set<typename T> 学习

    转自http://blog.csdn.net/mmzsyx/article/details/8240071 散列容器(hash container): 通常比二叉树的存储方式可以提供更高的访问效率.# ...

  4. C++11/14笔记

    目录 语言层面 模板表达式中的空格 nullptr和std::nullptr_t 自动推导类型----auto 一致性初始化----Uniform Initialization 初始化列表(initi ...

  5. 标准模板库(STL)

    组件: 容器:管理某类对象的集合. 迭代器:用来在一个对象集合内遍历元素. 算法:处理集合内的元素. 容器 序列式容器:顾名思义.array,vector,deque,list 和 forward_l ...

  6. 网易云 微专业C++系统工程师

    网易云 微专业C++系统工程师 一.学前基础 1.曾经学过某种编程语言(C语言最佳) 2.了解基本的变量.类型.作用域.循环和控制流程:了解基本数据类型(整数.浮点.字符串.数组等) 3.知道如何编译 ...

  7. 10--STL无序容器(Unordered Containers)

    一:无序容器简介 Unordered Containers也是一种关联式容器.其中元素是分散,没有定性的排列(不是图中那样松散).其中元素可能在某一次操作后改变原来的位置. 哈希表的链地址法,更能表现 ...

  8. STL学习笔记— —无序容器(Unordered Container)

    简单介绍 在头文件<unordered_set>和<unordered_map> 中定义 namespace std { template <typename T, ty ...

  9. 侯捷STL学习(十)--容器hashtable探索(unordered set/map)

    layout: post title: 侯捷STL学习(十) date: 2017-07-23 tag: 侯捷STL --- 第二十三节 容器hashtable探索 hashtable冲突(碰撞)处理 ...

随机推荐

  1. GJM : Python简单爬虫入门 (一) [转载]

    版权声明:本文原创发表于 [请点击连接前往] ,未经作者同意必须保留此段声明!如有侵权请联系我删帖处理! 为大家介绍一个简单的爬虫工具BeautifulSoup BeautifulSoup拥有强大的解 ...

  2. GJM:用C#实现网络爬虫(一) [转载]

    网络爬虫在信息检索与处理中有很大的作用,是收集网络信息的重要工具. 接下来就介绍一下爬虫的简单实现. 爬虫的工作流程如下 爬虫自指定的URL地址开始下载网络资源,直到该地址和所有子地址的指定资源都下载 ...

  3. 设计模式之 面向对象的养猪厂的故事,C#演示(二)

    (三) 优先使用聚合,而不是继承 有一段时间,养猪场的老板雇用了清洁工人来打扫猪舍.但有一天,老板忽然对自己说"不对啊,既然我有机器人,为什么还要雇人来做这件事情?应该让机器人来打扫宿舍!& ...

  4. spring常用注解使用解析

    spring没有采用约定优于配置的策略,spring要求显示指定搜索哪些路径下的Java文件.spring将会把合适的java类全部注册成spring Bean.   问题:spring怎么知道把哪些 ...

  5. canvas滤镜-刮刮乐

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. 10个最好的 JavaScript 动画库和开发框架

    虽然 CSS3 动画功能能够让我们以简单轻松的方式实现动画效果,但是浏览器兼容性问题让人头疼.不过不用担心,我们还有另外的武器——JavaScript,它同样可以帮助你实现各种各样的动画效果,而且借助 ...

  7. jQuery立体式数字滚动条增加

    1.html结构 <div class="numberRun1"></div> 2.js <script type="text/javasc ...

  8. sublime text3 之snippet编写代码片段

    sublime text 3 中有个强大的功能就是可以编写各种文件类型的snippet代码片段,可以节省大量的时间. 文件名为:jekyll-top.sublime-snippet(.sublime- ...

  9. Sass学习之路(5)——变量

    1.定义变量:Sass中定义变量的关键字是'$'(毕竟程序员缺钱),并使用冒号(:)进行赋值,例如: $width:200px;//定义了一个名为width的变量,值为200px 2.普通变量和默认变 ...

  10. JavaScript学习笔记-对象

    枚举对象的属性:通常用for(...in...)来循环遍历,由于 for in 总是要遍历整个原型链,因此如果一个对象的继承层次太深的话会影响性能 for(var i in foo){ if(foo. ...