有没有一种哈希函数可以生成唯一的哈希码(类似于MD5),并且能够保持顺序?
理论上:
如果我有100万个大小为1MB(1,048,576字节)的数据块,并且它们所有的差异都在最后10个字节,则一个块与另一个块的比较时间将是O(n-10)。如果我使用快速排序(使~(nlog2(n))次比较),则总比较时间将为nlog2(n)*(k-10)(其中k是块大小)
1'000'000 * 20 * (1'048'576 - 10)
有没有一种哈希函数可以生成唯一的哈希码(类似于MD5),并且能够保持顺序?
理论上:
如果我有100万个大小为1MB(1,048,576字节)的数据块,并且它们所有的差异都在最后10个字节,则一个块与另一个块的比较时间将是O(n-10)。如果我使用快速排序(使~(nlog2(n))次比较),则总比较时间将为nlog2(n)*(k-10)(其中k是块大小)
1'000'000 * 20 * (1'048'576 - 10)
CHM是一个算法,它生成保留顺序的最小完美哈希函数(例如,如果A < B,则h(A) < h(B))。每个键大约需要使用8个字节的存储空间。
一般情况下,除非哈希的大小至少与对象的大小相同,否则不可能存在这样的函数。
这个论点很简单:如果有N个对象但M < N个哈希值,根据pigeonhole principle,两个不同的对象被映射到一个哈希值,因此它们的顺序不会被保留。
然而,如果我们保证对象具有附加属性或放宽要求,则可能出现自定义或概率解决方案。
A < B
的情况下hash(A) <= hash(B)
,可以使用对象的前16个字节作为哈希。对于你的特定数据集来说,这16个字节有多大可能相等呢?也许你正在试图解决一个不存在的问题。 - GassaK
的N
个字符串数组进行排序,可以通过O(NK)
或O(N^2 + NK)
次字符比较来完成。S
中来构造它。对于每个新字符串P
,遍历它,并维护在S
中最大的字符串Q
的(非递减)索引,使得Q <= P
。当字符串P
结束时,在Q
之后将其插入到S
中。每个O(N)
的插入都可以在O(N+K)
操作内完成:O(N)
次增加索引分配到K
。
您需要一个输出16字节哈希值的函数。因此,会存在碰撞。您无法保留完美的顺序,也不想这样做。您能做到的最好的是:
H(x) < H(y) => x < y
H(x) > H(y) => x > y
接近的值将具有相同的哈希值。
H(x) = H(x + i_x) < H(x + i_x + 1)
。(除了末尾,因为x + i_x + 1
会超出1MB的块。)扩展后,您可以得到:对于任何n > 0
,都有H(x) < H(x + i_x + n)
。
另一方向上,j_x > 0的情况也适用于相同的论证。将它们结合起来,您就得到了:
H(x - j_x) == H(x - j_x + 1) == ... == H(x + i_x - 1) == H(x + i_x)
换句话说,对于每个哈希值,都有一个单独的段[a,b]映射到相同的值。在此段之外的任何值都不能具有相同的哈希值,否则将违反排序规则。
您的哈希函数可以由您选择的段来描述:
让a_i为1MB块,其中0 <= i < 256^16
且a_i <= a_i+1
。然后,您的哈希函数就被描述为:
H(x) = i where a_i <= x < a_i+1
要确保每个段的大小完全相同的唯一方法是使用:
a_i = i * 2 ^ (1MB - 16)
换句话说:H(x) = x的前16个字节。
任何其他保持顺序的哈希函数,其输出为16字节,对于随机输入块集合来说都不够高效。
是的,如果除了每个输入块的最后几位之外,所有其他位都相同,那么每个测试都会发生冲突。这是一种始终存在的最坏情况。如果您知道您的输入不是均匀随机的,则可以调整每个段的大小以具有相同的命中概率。但这需要了解可能的输入。
注意:如果您真的想要对1'000'000个1MB块进行排序,并担心这样的最坏情况,那么您可以使用桶排序,每次结果为1,000,000 * 1'048'576(字节)比较。如果您一次比较16位值,则其中一半仍具有合理数量的桶(65536)。
理论上不存在这样的事情。如果您想要,可以创建一个组合哈希:
索引:MD5
我认为这将解决您的需求。