当前位置: 首页 > news >正文

南通市住房和建设局网站广告软文小故事200字

南通市住房和建设局网站,广告软文小故事200字,电子商务静态网站建设实验报告,自己做购物网站今天看STL hash_map的源码的时候,出于好奇,我看了一个stl里面是用使用什么哈希函数,把key的转换为哈希值的,猜测这里的哈希函数肯定是基于线性同余变种过来的。为什么要对key做变化?这是因为我们使用map的时候&#xf…

今天看STL hash_map的源码的时候,出于好奇,我看了一个stl里面是用使用什么哈希函数,把key的转换为哈希值的,猜测这里的哈希函数肯定是基于线性同余变种过来的。为什么要对key做变化?这是因为我们使用map的时候,我们会指定某个键值对:key和value。比如{“name”:“jmh”},在c++内部就会先使用一个pair把这种二元关系对存储下来,然后在对key计算哈希值,用hash值来组织起这些实际的pair。

对于一个键值对key和value,可以逻辑上可以理解为stl内部使用一个三元组(hash(key),key,value)来标识这个数据,然后再根据hash(key)把数据组织起来。

STL里面的哈希函数,主要是分两个情况:一个key本身是int,另外一种是key是字符串的情况。
我看了两个版本的stl源码。
一个是SGI STL 版本的,这个是20年前的代码,比较简单:
key为字符串:

inline size_t __stl_hash_string(const char* s)
{unsigned long h = 0; for ( ; *s; ++s)h = 5*h + *s;return size_t(h);
}
__STL_TEMPLATE_NULL struct hash<char*>
{size_t operator()(const char* s) const { return __stl_hash_string(s); }
};__STL_TEMPLATE_NULL struct hash<const char*>
{size_t operator()(const char* s) const { return __stl_hash_string(s); }
};

key为整数:直接就是恒等映射了,也就是hash(key)=key

__STL_TEMPLATE_NULL struct hash<int> {size_t operator()(int x) const { return x; }
};
__STL_TEMPLATE_NULL struct hash<unsigned int> {size_t operator()(unsigned int x) const { return x; }
};
__STL_TEMPLATE_NULL struct hash<long> {size_t operator()(long x) const { return x; }
};
__STL_TEMPLATE_NULL struct hash<unsigned long> {size_t operator()(unsigned long x) const { return x; }

另外一个是VS2013里面的实现:
key为字符串:
我们只看32位的实现,这里就使用了很大的起始值和乘积素数。

inline size_t _Hash_seq(const unsigned char *_First, size_t _Count){	// FNV-1a hash function for bytes in [_First, _First+_Count)#if defined(_M_X64) || defined(_LP64) || defined(__x86_64) || defined(_WIN64)static_assert(sizeof(size_t) == 8, "This code is for 64-bit size_t.");const size_t _FNV_offset_basis = 14695981039346656037ULL;const size_t _FNV_prime = 1099511628211ULL;#else /* defined(_M_X64), etc. */static_assert(sizeof(size_t) == 4, "This code is for 32-bit size_t.");const size_t _FNV_offset_basis = 2166136261U;const size_t _FNV_prime = 16777619U;#endif /* defined(_M_X64), etc. */size_t _Val = _FNV_offset_basis;for (size_t _Next = 0; _Next < _Count; ++_Next){	// fold in another byte_Val ^= (size_t)_First[_Next];_Val *= _FNV_prime;}#if defined(_M_X64) || defined(_LP64) || defined(__x86_64) || defined(_WIN64)static_assert(sizeof(size_t) == 8, "This code is for 64-bit size_t.");_Val ^= _Val >> 32;#else /* defined(_M_X64), etc. */static_assert(sizeof(size_t) == 4, "This code is for 32-bit size_t.");#endif /* defined(_M_X64), etc. */return (_Val);}

key为整数:

	size_t operator()(const _Kty& _Keyval) const{	// hash _Keyval to size_t value by pseudorandomizing transformlong _Quot = (long)(hash_value(_Keyval) & LONG_MAX);ldiv_t _Qrem = _CSTD ldiv(_Quot, 127773);_Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;if (_Qrem.rem < 0)_Qrem.rem += LONG_MAX;return ((size_t)_Qrem.rem);}

首先这个函数是把keyval在做一次映射,把它的值转换为新的数字,这么做的好处是使得hash_map的性能不会因为输入数据的随机性的优劣而有较大的的变化,因为不管输入数据key随机与否,这个函数函数都会把哈希值搞的很随机。

这个函数就很有意思了,居然会硬编码 16807和12773,2836,这些数字看起来很奇怪呀???这几个数字意味着什么呢?

查了文献才知道,这几个数还大有文章!

这几个数来自基于线性同余的伪随机数发生器,一般来说:
伪随机数发生器的核心步骤就两个:
1.vnext=vprevious∗a%m1.v_{next}=v_{previous}*a \%\space m1.vnext=vpreviousa% m
2.vprevious=vnext2.v_{previous}=v_{next}2.vprevious=vnext
通常m会取成 231−12^{31}-12311
而这个不同的aaa 的取值就大有讲究了,不同的a 会导致不同的循环周期。这里的循环周期是指,令vpreviousv_{previous}vprevious为一个初始值xxx 出发,不断的计算vnextv_{next}vnext ,如此往复,直到vnextv_{next}vnext又回到xxx初始值,其中的迭代次数就是循环周期了。显然循环周期越长越好,因为循环周期越长,随机数能取的值就越多,当把这种随机数当做hash值的时候它就越不会发生冲突。

经过上个世纪70年代的研究,人们发现当aaa168071680716807 这个素数的时候,不管初始值xxx 取啥,它的循环周期特别大就是等于231−12^{31}-12311

// The sequence of values this PRNG should produce includes:
// 
//      Result     Number of results after seed of 1
//
//       16807          1
//   282475249          2
//  1622650073          3
//   984943658          4
//  1144108930          5
//   470211272          6
//   101027544          7
//  1457850878          8
//  1458777923          9
//  2007237709         10
//
//   925166085       9998
//  1484786315       9999
//  1043618065      10000
//  1589873406      10001
//  2010798668      10002
//
//  1227283347    1000000
//  1808217256    2000000
//  1140279430    3000000
//   851767375    4000000
//  1885818104    5000000
//
//   168075678   99000000
//  1209575029  100000000
//   941596188  101000000
//
//  1207672015 2147483643
//  1475608308 2147483644
//  1407677000 2147483645
//           1 2147483646
//       16807 2147483647

至于12773,2836这两个数,存在以下关系:

#define a 16807         /* multiplier */
#define m 2147483647L   /* 2**31 - 1 */
#define q 127773L       /* m div a */
#define r 2836          /* m mod a */

而且有:

def hash1(val):return (val * 16801)%constmdef hash2(val):q=val//127773r=val%127773return 16807*r-2836*q

两个函数是等价的!VS2013使用第二种实现,就不用模运行了,只需要除法即可。

http://www.lbrq.cn/news/2585395.html

相关文章:

  • 向国旗致敬做时代新人网站网络科技公司网站建设
  • 网站搜索优化靠谱seo研究中心培训机构
  • 秦皇岛北京网站建设怎么接推广
  • 网站开发调研站长之家网站排行榜
  • 北京网站改版营销推广外包
  • 东莞南城网站开发公司免费网站大全
  • 网站建设培训会上的讲话查淘宝关键词排名软件有哪些
  • 百度竞价镇江seo网页的基础知识
  • 做局域网站数据库客户管理软件哪个好用
  • 织梦门户网站源码专业代写软文
  • 中国最好网站建设公司哪里能搜索引擎优化
  • 网站反链数武汉seo服务多少钱
  • 外包公司做网站的流程设计网站用什么软件
  • c做网站怎样做网站的优化、排名
  • 最好的网站制作公司windows优化大师官方网站
  • 兰州关键词网络推广广州seo报价
  • 云南网站建设效果好吗电商网站链接买卖
  • 网站改版打造全新网站seo免费
  • 百度不收录哪些网站吗百度网盘app怎么打开链接
  • 织梦系统怎么复制网站模板优化大师好用吗
  • 枣庄公司做网站百度关键词优化策略
  • 汕头网站推广公司网站排名提升软件
  • 贵州建设监理协会网站进不了百度快照怎么删除
  • 搭建网站服务vi设计
  • 南京网站建设有限公司百度客服在线咨询人工服务
  • 网站如何留住客户百度竞价一个月5000够吗
  • 又一个wordpress站点企业网站推广技巧
  • 建立企业网站步骤官网seo
  • 哈尔滨建设网站门户今日小说搜索风云榜
  • 做网站开发没有人带营销软文300字
  • sqli-labs通关笔记-第30关GET字符注入(WAF绕过 双引号闭合 手工注入+脚本注入两种方法)
  • 13015计算机系统原理-速记宝典
  • LLM大模型开发-SpringAI:ChatClient、Ollama、Advisor
  • WebMvc自动配置流程讲解
  • C的运算符与表达式
  • Compose笔记(四十一)--ExtendedFloatingActionButton