汇编刚学跳跃表,发现跳跃表与hash有着数不清的关系
维基百科:
哈希表(哈希映射)是实现关联数组抽象数据类型的数据结构,该结构可以将键映射到值。哈希表使用哈希函数来计算桶或槽阵列的索引,从中可以找到所需的值。
理想情况下,散列函数会将每个密钥分配给一个唯一的存储桶,但大多数散列表设计采用不完美的散列函数,这可能会导致散列冲突,其中散列函数为多个密钥生成相同的索引。必须以某种方式适应这种碰撞。
在尺寸合适的哈希表中,每次查找的平均成本(指令数)与表中存储的元素数无关。许多哈希表设计还允许键值对的任意插入和删除,在(摊销[2])每个操作的恒定平均成本。[3] [4]
在许多情况下,哈希表平均比搜索树或任何其他表查找结构更有效。因此,它们被广泛用于多种计算机软件中,特别是用于关联数组,数据库索引,高速缓存和集合。
处理跳跃表,哈希表是一个实现方式,哈希表是根据关键字(Key value)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做哈希表,也叫散列表。
哈希是大数据技术的基础,大家应该都有了解了,这里就不深度展开了,算法导论有一章已经讲得非常清楚了,这里说说我觉得比较有意思的一个哈希的东西。
哈希表的核心是哈希算法,一个好的哈希算法可以让碰撞产生得更少,查找速度越接近于O(1),所以一个好的哈希算法非常重要。
哈希算法很多,说都说不完,不同的算法适应不同的场景,我知道的,传说中有一个哈希算法,来自魔兽世界(!!!!为了部落!!!!),号称暴雪哈希,该算法产生的哈希值完全无法预测,被称为"One-Way Hash"( A one-way hash is a an algorithm that is constructed in such a way that deriving the original string (set of strings, actually) is virtually impossible)。
// 初始化hash计算需要的基础map table func initCryptTable() { var seed, index1, index2 uint64 = 0x00100001, 0, 0 i := 0 for index1 = 0; index1 < 0x100; index1 += 1 { for index2, i = index1, 0; i < 5; index2 += 0x100 { seed = (seed*125 + 3) % 0x2aaaab temp1 := (seed & 0xffff) << 0x10 seed = (seed*125 + 3) % 0x2aaaab temp2 := seed & 0xffff cryptTable[index2] = temp1 | temp2 i += 1 } } } // hash, 以及相关校验hash值 func HashKey(lpszString string, dwHashType int) uint64 { i, ch := 0, 0 var seed1, seed2 uint64 = 0x7FED7FED, 0xEEEEEEEE var key uint8 strLen := len(lpszString) for i < strLen { key = lpszString[i] ch = int(toUpper(rune(key))) i += 1 seed1 = cryptTable[(dwHashType<<8)+ch] ^ (seed1 + seed2) seed2 = uint64(ch) + seed1 + seed2 + (seed2 << 5) + 3 } return uint64(seed1) }