- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想实现一个hashmap,但我不允许让它扩展。因为我确实知道我最多需要存储 N
个元素,所以我可以为哈希表的每个存储桶预先分配一个包含 N
个元素的数组,这样我仍然可以在最坏的情况下存储 N
个元素,即所有键都在同一个存储桶上进行散列。但我需要存储的元素相当大,因此对于较大的 N
来说,这对内存的使用效率非常低。
是否可以使用固定数量的内存高效(就内存而言)实现 HashMap ,例如通过实现智能哈希函数?
(P.S.: key 是一个无符号的 32 位整数,我对 key 没有先验知识,除了我将收到的 key 值位于该范围的一个相当小的子集中,并且该子集向上移动非常缓慢范围内。)
我现在有一个实现,其中有两个长度为 N 的数组,一个包含元素,另一个包含与位置 i
处的元素相对应的键两个数组。我使用模运算作为哈希函数来确定元素应插入/存在的位置,并使用线性探针来查找发生碰撞时最近的空点。我认为这的复杂度为 O(N),并且我认为对于我期望的数据量来说,这将相当快地工作。我问这个问题是为了看看是否可以做得更好。
最佳答案
对于散列,您可以使用以下代码片段,顺便说一句,Linux 内核使用它来散列 PID:
unsigned long hash_long(unsigned long val, unsigned int bits)
{
unsigned long hash = val * 0x9e370001UL;
return hash >> (32 - bits);
}
魔数(Magic Number)0x9e370001UL
是一个很大的素数。以下是理解 Linux 内核的摘录,解释了这个神奇的数字:
You might wonder where the 0x9e370001 constant (= 2,654,404,609) comes from. This hash function is based on a multiplication of the index by a suitable large number, so that the result overflows and the value remaining in the 32-bit variable can be considered as the result of a modulus operation. Knuth suggested that good results are obtained when the large multiplier is a prime approximately in golden ratio to 232 (32 bit being the size of the 80×86’s registers). Now, 2,654,404,609 is a prime near to that can also be easily multiplied by additions and bit shifts, because it is equal to 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1.
右移 hash >> (32 - 位);
只是表示在哈希值中保留 bits 位数。其他位将被清零。在您的情况下,位将由限制N
确定。为了使其按原样工作,N
需要设置其最高有效设置位之后的所有位,例如对于 N = 7
(最后三位均已设置且所有其他位均为零),bits 将为 3。或者 N = 63
其中最低有效六位均已设置,所有其他位均为零。这里位将为6。
hash_long
函数返回的值将形成数组的索引。
处理碰撞
为了处理冲突,只保留一个数组,但使其成为链表节点的数组。所以数组中的每个元素都指向一个链表。当发生冲突时,只需将新条目附加到与数组中该插槽对应的链表末尾。
处理碰撞(更新)
如果您无法动态分配新内存,那么您发布的解决方案似乎很好,尽管我不确定仅包含键的数组的用途是什么(键不应该是它所属元素的成员吗? )。以下是对您的解决方案的建议:
拥有一维数组意味着在发生碰撞时,我们在插入和检索时都会执行线性探测。另一种方法是使用一个二维数组,其中内部数组充当链表。我们需要插入每个内部数组中最后一个元素的索引。与一维数组相比的缺点是,如果同一索引上发生太多冲突,那么我们可能会耗尽其中一个内部数组的空间,除非我们也将每个内部数组的长度设置为 N,这将导致大量浪费空间。优点是插入时我们不需要进行线性探测。我们只需检查内部数组中最后一个元素的索引并将其加一以获得下一个槽以插入新元素。
关于c - 如何实现固定大小的 HashMap ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24203858/
背景: 我最近一直在使用 JPA,我为相当大的关系数据库项目生成持久层的轻松程度给我留下了深刻的印象。 我们公司使用大量非 SQL 数据库,特别是面向列的数据库。我对可能对这些数据库使用 JPA 有一
我已经在我的 maven pom 中添加了这些构建配置,因为我希望将 Apache Solr 依赖项与 Jar 捆绑在一起。否则我得到了 SolarServerException: ClassNotF
interface ITurtle { void Fight(); void EatPizza(); } interface ILeonardo : ITurtle {
我希望可用于 Java 的对象/关系映射 (ORM) 工具之一能够满足这些要求: 使用 JPA 或 native SQL 查询获取大量行并将其作为实体对象返回。 允许在行(实体)中进行迭代,并在对当前
好像没有,因为我有实现From for 的代码, 我可以转换 A到 B与 .into() , 但同样的事情不适用于 Vec .into()一个Vec . 要么我搞砸了阻止实现派生的事情,要么这不应该发
在 C# 中,如果 A 实现 IX 并且 B 继承自 A ,是否必然遵循 B 实现 IX?如果是,是因为 LSP 吗?之间有什么区别吗: 1. Interface IX; Class A : IX;
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在阅读标准haskell库的(^)的实现代码: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 a -> b ->a expo x0
我将把国际象棋游戏表示为 C++ 结构。我认为,最好的选择是树结构(因为在每个深度我们都有几个可能的移动)。 这是一个好的方法吗? struct TreeElement{ SomeMoveType
我正在为用户名数据库实现字符串匹配算法。我的方法采用现有的用户名数据库和用户想要的新用户名,然后检查用户名是否已被占用。如果采用该方法,则该方法应该返回带有数据库中未采用的数字的用户名。 例子: “贾
我正在尝试实现 Breadth-first search algorithm , 为了找到两个顶点之间的最短距离。我开发了一个 Queue 对象来保存和检索对象,并且我有一个二维数组来保存两个给定顶点
我目前正在 ika 中开发我的 Python 游戏,它使用 python 2.5 我决定为 AI 使用 A* 寻路。然而,我发现它对我的需要来说太慢了(3-4 个敌人可能会落后于游戏,但我想供应 4-
我正在寻找 Kademlia 的开源实现C/C++ 中的分布式哈希表。它必须是轻量级和跨平台的(win/linux/mac)。 它必须能够将信息发布到 DHT 并检索它。 最佳答案 OpenDHT是
我在一本书中读到这一行:-“当我们要求 C++ 实现运行程序时,它会通过调用此函数来实现。” 而且我想知道“C++ 实现”是什么意思或具体是什么。帮忙!? 最佳答案 “C++ 实现”是指编译器加上链接
我正在尝试使用分支定界的 C++ 实现这个背包问题。此网站上有一个 Java 版本:Implementing branch and bound for knapsack 我试图让我的 C++ 版本打印
在很多情况下,我需要在 C# 中访问合适的哈希算法,从重写 GetHashCode 到对数据执行快速比较/查找。 我发现 FNV 哈希是一种非常简单/好/快速的哈希算法。但是,我从未见过 C# 实现的
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化
1. 绪论 在前面文章中提到 空间直角坐标系相互转换 ,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换。这个就是我们经常在测绘数据处理中,WGS-84坐标系、54北京坐标系
在软件开发过程中,有时候我们需要定时地检查数据库中的数据,并在发现新增数据时触发一个动作。为了实现这个需求,我们在 .Net 7 下进行一次简单的演示. PeriodicTimer .
二分查找 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
我是一名优秀的程序员,十分优秀!