技术在于交流、沟通,本文为博主原创文章转载请注明出处并保持作品的完整性

在前面我介绍过hash的使用,本次主要介绍一下Hash Function

Hash Function即获得hash code的函数,根据其获得的hash code放到指定的bucket中,那么为了保证其hash的效率我们应尽量避免碰撞,所以hash Function所产生的hash code应足够的乱

下面介绍一个万用的hash function及其测试代码

首先我们创建一个客户类,它有三个成员变量 姓,名,年龄

class Customer
{
public:
string mFirstName;
string mLastName;
string mAge;
Customer(string firstName, string lastName, string age):mFirstName(firstName),mLastName(lastName),mAge(age){}
};

下面我们来创建hash function

class CustomerHash
{
public:
std::size_t operator()(const Customer& c) const
{
return hash_val(c.mFirstName, c.mLastName, c.mAge);
} template <typename... Types>
size_t hash_val(const Types&... args)const
{
size_t seed = ;//seed 为需要返回的hash code
hash_value(seed, args...);//C++11 新语法 我在http://www.cnblogs.com/LearningTheLoad/p/7208680.html中有介绍
return seed;
} template <typename T, typename... Types>
void hash_value(size_t& seed,
const T& firstArg,
const Types&... args) const
{
hash_combine(seed, firstArg);
hash_value(seed, args...);
} template <typename T>
void hash_value(size_t& seed,
const T& val) const //参数仅剩一个时
{
hash_combine(seed, val);
} template<typename T>
void hash_combine(size_t& seed,
const T& val) const
{
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << ) + (seed >> ); //0x9e3779b9 黄金分割比例
}
};

测试代码

int main(int argc, char *argv[])
{
unordered_multiset<Customer, CustomerHash> set; set.insert(Customer("a", "b", ""));
set.insert(Customer("c", "d", ""));
set.insert(Customer("e", "f", ""));
set.insert(Customer("g", "h", "")); int myBucket_count = set.bucket_count();//返回有多少个篮子
cout << set.bucket_count() << endl; CustomerHash hh;
cout << "bucket postion of " << hh(Customer("a", "b", "")) %myBucket_count << endl;//取余后 得出落在哪个篮子上
cout << "bucket postion of " << hh(Customer("c", "d", "")) %myBucket_count << endl;
cout << "bucket postion of " << hh(Customer("e", "f", "")) %myBucket_count << endl;
cout << "bucket postion of " << hh(Customer("a", "b", "")) %myBucket_count << endl; for (int i = ; i< myBucket_count; i++)
{//检测落在哪个篮子上
cout << "bucket at #: " << i << "has: " << set.bucket_size(i) << endl;
}
return ;
}

测试结果

全部测试代码

#include <iostream>
#include <unordered_set> using namespace std; class Customer
{
public:
string mFirstName;
string mLastName;
string mAge; Customer(string firstName, string lastName, string age):mFirstName(firstName),mLastName(lastName),mAge(age){} operator ==(const Customer& c) const
{
return (mFirstName == c.mFirstName && mLastName == c.mLastName && mAge == c.mAge);
}
}; class CustomerHash
{
public:
std::size_t operator()(const Customer& c) const
{
return hash_val(c.mFirstName, c.mLastName, c.mAge);
} template <typename... Types>
size_t hash_val(const Types&... args)const
{
size_t seed = ;
hash_value(seed, args...);
return seed;
} template <typename T, typename... Types>
void hash_value(size_t& seed,
const T& firstArg,
const Types&... args) const
{
hash_combine(seed, firstArg);
hash_value(seed, args...);
} template <typename T>
void hash_value(size_t& seed,
const T& val) const
{
hash_combine(seed, val);
} template<typename T>
void hash_combine(size_t& seed,
const T& val) const
{
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << ) + (seed >> );
}
}; int main(int argc, char *argv[])
{
unordered_multiset<Customer, CustomerHash> set; set.insert(Customer("a", "b", ""));
set.insert(Customer("c", "d", ""));
set.insert(Customer("e", "f", ""));
set.insert(Customer("g", "h", "")); int myBucket_count = set.bucket_count();
cout << set.bucket_count() << endl; CustomerHash hh;
cout << "bucket postion of " << hh(Customer("a", "b", "")) %myBucket_count << endl;
cout << "bucket postion of " << hh(Customer("c", "d", "")) %myBucket_count << endl;
cout << "bucket postion of " << hh(Customer("e", "f", "")) %myBucket_count << endl;
cout << "bucket postion of " << hh(Customer("a", "b", "")) %myBucket_count << endl; for (int i = ; i< myBucket_count; i++)
{
cout << "bucket at #: " << i << "has: " << set.bucket_size(i) << endl;
}
return ;
}

这是一个万用的hash function ,在我们自定义hash function时就可以定义为上面的函数

参考侯捷<<STL源码剖析>>

STL标准库-一个万用的hash function的更多相关文章

  1. STL标准库-容器-set与multiset

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. set与multiset关联容器 结构如下 set是一种关联容器,key即value,value即key.它是自动排序,排序特点依据key se ...

  2. STL标准库-容器-deque

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. deque双向开口可进可出的容器 我们知道连续内存的容器不能随意扩充,因为这样容易扩充别人那去 deque却可以,它创造了内存 ...

  3. STL标准库-容器-vector

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. 向量容器vector是一个动态数组,内存连续,它是动态分配内存,且每次扩张的原来的二倍. 他的结构如下 一 定义 vector ...

  4. C++STL标准库学习笔记(五)set

    前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来,这一篇后面主要都是我的记录了,为了防止大片蓝色字体出现,后面就不改蓝色 ...

  5. C++STL标准库学习笔记(三)multiset

    C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...

  6. C++STL标准库学习笔记(二)二分查找

    二.STL中的二分查找算法 1.binary_search 2.lower_bound 3.upper_bound 记得#include<algorithm>! 前言: 在这个笔记中,我把 ...

  7. STL标准库-算法-常用算法

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 介绍11种STL标准库的算法,从这11种算法中总结一下算法的基本使用 1.accumulate() 累加 2.for_each( ...

  8. STL标准库-容器-set与map

    STL标准库-容器-set与multiset C++的set https://www.cnblogs.com/LearningTheLoad/p/7456024.html STL标准库-容器-map和 ...

  9. C++STL标准库学习笔记(一)sort

    前言: 近来在学习STL标准库,做一份笔记并整理好,方便自己梳理知识.以后查找,也方便他人学习,两全其美,快哉快哉! 这里我会以中国大学慕课上北京大学郭炜老师的<程序设计与算法(一)C语言程序设 ...

随机推荐

  1. Python time strptime()与time strftime()

    time strftime()接收时间元组,返回表示时间的字符串. time strptime()把时间字符串,解析成一个时间元组. import time t = time.strftime('%Y ...

  2. Ubuntu 登陆界面无限循环问题 以及 root用户无法使用命令问题

    在Ubuntu下配置好了eclipse之后,马上着手用eclipse试运行ns3.在./waf编译的时候出现了"Permission denied"问题. 在网络上查阅了相关资料之 ...

  3. Apache+Php+Mariadb+NFS+discuz

    安装LAMP服务器,并利用discuz做测试 nfs + discuz      192.168.108.158 php + DNS        192.168.108.160 apache     ...

  4. HDU 1213 How Many Tables(并查集模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1213 题意: 这个问题的一个重要规则是,如果我告诉你A知道B,B知道C,这意味着A,B,C知道对方,所以他们可以 ...

  5. Goroutines和Channels(二)

    网络编程是并发大显身手的一个领域,由于服务器是最典型的需要同时处理很多连接的程序,这些连接一般来自于彼此独立的客户端. 本小节,我们会讲解go语言的net包,这个包提供编写一个网络客户端或者服务器程序 ...

  6. Python day8常用格式化format类2

    format常用格式化 tp1="i am {},age {},{}".format('LittlePage',18,'boy') tp2="i am {},age {} ...

  7. pandas.read_csv参数整理

    读取CSV(逗号分隔)文件到DataFrame,也支持文件的部分导入和选择迭代 更多帮助参见:http://pandas.pydata.org/pandas-docs/stable/io.html 参 ...

  8. [JSBSim]基于winsocket2的TCP\UDP使用例子

    TCP部分: 参考:http://blog.csdn.net/sbfksmq/article/details/50808863 另附:linux下的tcp/udp参考:https://www.cnbl ...

  9. spring boot 邮件发送(带附件)

    首先开启QQ邮箱的POP.SMTP服务器,获取授权码. 设置-->账户-->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 pom.xml需要加载三个ja ...

  10. android中 检查网络连接状态的变化,无网络时跳转到设置界面

    1:在AndroidManifest.xml中加一个声明 <receiver android:name="NetCheckReceiver">    <inten ...