map和hash_map

今天在写拼流的程序时碰到一个问题,要根据流的四元组的结构信息映射到该流的数据。也就是我在网络数据包拼接的过程中,要根据包的地址和端口信息,对应到其对应的一个流的数据上去,把端口和地址信息相同的包的数据段中的数据组装起来。自然想到用map,不过map要求其关键码类型提供一个小于操作,而我的这种四元组信息没有大小的关系,于是自然就想到用hash_map。
    hash_map基于哈希表,它对数据的存储和查找所需的时间大大降低,几乎可以看成是常数时间(理想情况下是O(1))。其代价是消耗比较多的内存,不过在某些情况下用空间换时间的做法是值得的。
    hash_map的声明大致是这样的:

template <class _Key, class _Tp, class _HashFcn = hash<_Key>,class _EqualKey = equal_to<_Key>,class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >class hash_map{        ...}

hash_map的基本原理是使用一个下标范围比较大的数组来存储元素。需要提供一个散列函数(hash函数),使得每个关键字都与一个函数值(即数组下标,hash值)相对应,于是用这个数组单元来存储这个元素。除了定义一个hash函数外,还需提供一个比较其关键码是否相等的函数。对于STL的内部类型的关键码,hash函数和equal_to函数可以省略,STL会提供缺省的函数。不过对于自定义结构的关键码,就必须自己提供hash函数和比较函数。
    在声明自己的哈希函数时要注意以下几点:

  1. 使用struct,然后重载operator().
  2. 返回是size_t
  3. 参数是你要hash的key的类型。
  4. 函数是const类型的。

例如:

//如果要自己定义字符串hash函数,你可以这样写:
struct str_hash{

        size_t operator()(const string& str) const        {
										unsigned
										long __h = 0;
										for (size_t i = 0 ; i < str.size() ; i ++)                __h = 5*__h + str[i];
										return size_t(__h);        }};

对于比较函数,应该就比较简单了。
map和hash_map性能分析:
    选择map容器,是为了更快的从关键字查找到相关的对象。与使用list这样的线性表容器相比,一可以简化查找的算法,二可以使任意的关键字做索引,并与 目标对象配对,优化查找算法。在C++的STL中map是使用树来做查找算法,这种算法差不多相当与list线性容器的折半查找的效率一样,都是O (log2N),而list就没有map这样易定制和操作了。 
相比hash_map,hash_map使用hash表来排列配 对,hash表是使用关键字来计算表位置。当这个表的大小合适,并且计算算法合适的情况下,hash表的算法复杂度为O(1)的,但是这是理想的情况下 的,如果hash表的关键字计算与表位置存在冲突,那么最坏的复杂度为O(n)。
    总体来说,hash_map 查找速度会比map快,其查找速度基本和数据量大小无关,属于常数级别;而map的查找速度是log(n)级别。hash_map的缺点是性能不稳定,且占用较多内存。这就需要权衡了。
    树查找,在总查找效率上比不上hash表,但是它很稳定,它的算法复杂度不会出现波动。在一次查找中,你可以断定它最坏的情况下其复杂度不会超过O (log2N)。而hash表就不一样,是O(1),还是O(N),或者在其之间,你并不能把握。假若你在开发一个供外部调用的接口,其内部有关键字的查 找,但是这个接口调用并不频繁,你是会希望其调用速度快、但不稳定呢,还是希望其调用时间平均、且稳定?反之假若你的程序需要查找一个关键字,这个操作 非常频繁,你希望这些操作在总体上的时间较短,那么hash表查询在总时间上会比其他要短,平均操作时间也会短。 
总结一下,选用map还是hash_map,关键是看关键字查询操作次数,以及你所需要保证的是查询总体时间还是单个查询的时间。如果是要很多次操 作,要求其整体效率,那么使用hash_map,平均处理时间短。如果是少数次的操作,使用hash_map可能造成不确定的O(N),那么使用平均处理 时间相对较慢、单次处理时间恒定的map,考虑整体稳定性应该要高于整体效率,因为前提在操作次数较少。如果在一次流程中,使用hash_map的少数操 作产生一个最坏情况O(N),那么hash_map的优势也因此丧尽了。
    下面摘录使用hash_map的一个例子,我的程序就是参考的这个例子:(对于自定义的结构,为它定义一个好的hash函数是最重要的,这个例子中的hash函数定义很简单。。。)
#include <hash_map>
#include <string>
#include <iostream>
using
namespace std;
//define the class
class ClassA{
public:
ClassA(int a):c_a(a){}
int getvalue()const { return c_a;}
void setvalue(int a){c_a;}
private:
int c_a;
};
//1 define the hash function
struct hash_A{
size_t operator()(const
class ClassA & A)const{
// return hash<int>(classA.getvalue());
return A.getvalue();
}
};
//2 define the equal function
struct equal_A{
bool
operator()(const
class ClassA & a1, const
class ClassA & a2)const{
return a1.getvalue() == a2.getvalue();
}
};

int main()
{
hash_map<ClassA, string, hash_A, equal_A> hmap;
ClassA a1(12);
hmap[a1]="I am 12";
ClassA a2(198877);
hmap[a2]="I am 198877";

cout<<hmap[a1]<<endl;
cout<<hmap[a2]<<endl;
return 0;
}

后来弄了半天,发现VC6下竟没有hash_map头文件,ft....。ms当年VC6出来的时候hash_map还没有成为STL标准吧。转而奔到.net2003下,还是编译不过,再ft....现在正下.net 2005中,希望能支持hash_map,不然就只能单独下一个STL库安装上了。

支持(0)反对(0)

Map和hash_map的更多相关文章

  1. map,hash_map, hash_table, 红黑树 的原理和使用

    在刷算法题的时候总是碰到好多题,号称可以用hash table来解题.然后就蒙圈了. 1.首先,map和hash_map的区别和使用: (1)map底层用红黑树实现,hash_map底层用hash_t ...

  2. STL中map与hash_map容器的选择收藏

    这篇文章来自我今天碰到的一个问题,一个朋友问我使用map和hash_map的效率问题,虽然我也了解一些,但是我不敢直接告诉朋友,因为我怕我说错了,通过我查询一些帖子,我这里做一个总结!内容分别来自al ...

  3. map与hash_map使用与对比

    #include <iostream> #include <functional> #include <map> #include <ext/hash_map ...

  4. STL 中的map 与 hash_map的理解

    可以参考侯捷编著的<STL源码剖析> STL 中的map 与 hash_map的理解 1.STL的map底层是用红黑树存储的,查找时间复杂度是log(n)级别: 2.STL的hash_ma ...

  5. STL中的map和hash_map

    以下全部copy于:http://blog.chinaunix.net/uid-26548237-id-3800125.html 在网上看到有关STL中hash_map的文章,以及一些其他关于STL ...

  6. map、hash_map、unordered_map 的思考

    #include <map> map<string,int> dict; map是基于红黑树实现的,可以快速查找一个元素是否存在,是关系型容器,能够表达两个数据之间的映射关系. ...

  7. map vs hash_map

    1. map, multimap, set, multiset g++ 中 map, multimap, set, multiset 由红黑树实现 map: bits/stl_map.h multim ...

  8. map,hash_map和unordered_map 实现比较

    map介绍 Map是STL[1]的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处 ...

  9. STL中map与hash_map的比较

    1. map : C++的STL中map是使用树来做查找算法; 时间复杂度:O(log2N) 2. hash_map : 使用hash表来排列配对,hash表是使用关键字来计算表位置; 时间复杂度:O ...

随机推荐

  1. Leetcode#174 Dungeon Game

    原题地址 典型的地图寻路问题 如何计算当前位置最少需要多少体力呢?无非就是在向下走或向右走两个方案里做出选择罢了. 如果向下走,看看当前位置能提供多少体力(如果是恶魔就是负数,如果是草药就是正数),如 ...

  2. [百度空间] [转]内存屏障 - MemoryBarrier

    处理器的乱序和并发执行 目前的高级处理器,为了提高内部逻辑元件的利用率以提高运行速度,通常会采用多指令发射.乱序执行等各种措施.现在普遍使用的一些超标量处理器通常能够在一个指令周期内并发执行多条指令. ...

  3. UML建模类型(转载)

    区分UML模型, UML建模用于不同类型的不同的图.有三个重要类型的UML建模: 结构建模: 系统结构建模捕捉静态功能.它们包括下列各项: 类图 对象图 部署图 包图 复合结构图 组件图 结构模型代表 ...

  4. 【转】Sublime text 3 中文文件名显示方框怎么解决

    引用自:http://www.zhihu.com/question/24029280 如图,中文文件名打开全是乱码,内容倒是装了converttoutf8没什么太大的问题. 这个是sublime te ...

  5. 深入理解C# 静态类与非静态类、静态成员的区别

    静态类 静态类与非静态类的重要区别在于静态类不能实例化,也就是说,不能使用 new 关键字创建静态类类型的变量.在声明一个类时使用static关键字,具有两个方面的意义:首先,它防止程序员写代码来实例 ...

  6. 游戏引擎网络开发者的64做与不做(二A):协议与API

    [编者按]在这个系列之前的文章"游戏引擎网络开发者的64做与不做(一):客户端方面"中,Sergey介绍了游戏引擎添加网络支持时在客户端方面的注意点.本文,Sergey则将结合实战 ...

  7. 在Delphi中实现动画窗口

    Windows下有一个函数AnimateWindow,在Delphi自带的Win32 API Help中是找不到的.你可以在Delphi的编辑器中输入windows.等待代码向导出来,继续输入Anim ...

  8. 使用 Struts 2 开发 RESTful 服务

    REST 简介 REST 是英文 Representational State Transfer 的缩写,这个术语由 Roy Thomas Fielding 博士在他的论文<Architectu ...

  9. 妙味课堂——HTML+CSS(第四课)(二)

    单开一篇来讲一个大点的话题——清浮动    来看下例: <!DOCTYPE html> <html> <head> <meta charset="U ...

  10. Win7 _Object_header 中的 TypeIndex

    Win7 比较 xp下ObjectHeader中的内容有所变化,xp直接在OBJECT_HEADER里保存了POBJECT_TYPE指针,而Win7中把所有的对象类型放在了一个表里,这个表叫做ObTy ...