Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Language agnostic 创建可排序字符串的哈希_Language Agnostic_Sorting_Hash - Fatal编程技术网

Language agnostic 创建可排序字符串的哈希

Language agnostic 创建可排序字符串的哈希,language-agnostic,sorting,hash,Language Agnostic,Sorting,Hash,是否仍然可以创建字符串的散列,以便对散列进行排序,并获得与字符串本身排序相同的结果?除非字符串少于散列,并且散列是可排序的。即使这样,您仍然必须确保哈希顺序与字符串顺序相同,这可能是不可能的,除非您提前知道所有字符串。这将是不可能的,至少如果您允许字符串长度超过哈希大小。您有256^(最大字符串大小)可能的字符串映射到256^(哈希大小)哈希值,因此您将得到一些未排序的字符串 想象一下最简单的散列:将每个字符串截断为(散列大小)字节。否。散列必须包含与其替换的字符串相同数量的信息。否则,如果两个

是否仍然可以创建字符串的散列,以便对散列进行排序,并获得与字符串本身排序相同的结果?

除非字符串少于散列,并且散列是可排序的。即使这样,您仍然必须确保哈希顺序与字符串顺序相同,这可能是不可能的,除非您提前知道所有字符串。

这将是不可能的,至少如果您允许字符串长度超过哈希大小。您有256^(最大字符串大小)可能的字符串映射到256^(哈希大小)哈希值,因此您将得到一些未排序的字符串


想象一下最简单的散列:将每个字符串截断为(散列大小)字节。

否。散列必须包含与其替换的字符串相同数量的信息。否则,如果两个字符串映射到同一个哈希值,如何对它们进行排序


另一种思考方式是:如果我有两个字符串,“a”和“b”,那么我用这个保留排序的哈希函数对它们进行哈希,得到f(a)和f(b)。但是,有无限多的字符串大于“a”但小于“b”。这需要将字符串散列为任意精度的实值(因为基数)。最后,您基本上只需要将字符串编码为一个数字。

是。它被称为使用整个输入字符串作为散列。

正如其他人指出的那样,完全按照您的要求执行是不实际的。您必须使用字符串本身作为散列,这将限制可以“散列”的字符串的长度,等等

维护“排序哈希”数据结构的明显方法是维护排序列表(例如,堆或二叉树)和数据的哈希映射。插入和删除将是O(log(n)),而检索将是O(1)。我不确定这是否值得额外的复杂性和开销

如果您有一个特别大的数据集,大部分是只读的,并且对数时间检索过于昂贵,那么我认为它可能会有用。请注意,更新的成本实际上是常量时间(哈希)和对数时间(二叉树或堆)操作的总和。然而,在渐近分析过程中,O(1)+O(log(n))减小为两项中的较大项。(潜在成本仍然存在——与任何实施工作相关,无论其理论意义如何)

对于大范围的数据集大小,维护这种假设的混合数据结构的成本可以估计为维护两种纯数据结构的成本的“两倍”。(换句话说,二叉树的许多实现可以扩展到数十亿个元素(2^~32个左右),其时间成本与典型哈希函数的成本相当)。因此,我很难说服自己,这样增加的代码复杂性和运行时成本(混合数据结构)实际上对给定的项目有益


(注意:我看到Python 3.1.1添加了“有序”字典的概念……这与排序类似,但不完全相同。从我收集的数据来看,有序字典保留了元素插入集合的顺序。我似乎还记得一些关于“视图”的讨论…语言中的对象,这些对象可以以某种特定方式(排序、反转、反转排序等)访问字典的键,其成本(可能)低于通过内置的“sorted()”和“reversed()”传递键集的成本。我没有使用过这些,也没有查看过实现细节。我猜这些“视图”中的一个类似于一个延迟计算的索引,在调用时执行必要的排序,并使用某种标志或触发器(观察者模式或侦听器)存储结果,这些标志或触发器在后端源集合更新时重置。在该方案中,调用“视图”将更新其索引;子序列调用将能够使用这些结果,只要没有对字典进行插入或删除操作。在关键更改之后对视图的任何调用都将导致更新视图的成本。然而,这完全是我的猜测。我提到它是因为它还可能提供对你本质上是在问是否可以将键字符串压缩成更小的键,同时保留它们的排序顺序。所以这取决于你的数据。例如,如果字符串仅由十六进制数字组成,则可以将其替换为4位代码


但就一般情况而言,这是不可能做到的。您最终会将每个源密钥“散列”到自身中。

我偶然发现了这一点,尽管每个人的答案都是正确的,但我需要一个与此完全相同的解决方案来用于elasticsearch(不要问为什么)。有时候,我们并不需要一个完美的解决方案来解决所有的问题,我们只需要一个解决方案来处理可接受的约束。我的解决方案能够为字符串的第一个
n
字符生成可排序的hashcode,我做了一些初步测试,没有任何冲突。您需要预先定义所使用的
字符集
,并使用
n
将排序所需的第一个字符的值视为可接受的值,并尝试将结果哈希代码保持在定义类型的正间隔内,以使其正常工作,在我的情况下,对于Java Long类型,我最多可以使用13个字符。 下面是我用Java编写的代码,希望它能帮助其他需要它的人

String charset = "abcdefghijklmnopqrstuvwxyz";

public long orderedHash(final String s, final String charset, final int n) {
  Long hash = 0L;

  if(s.isEmpty() || n == 0)
    return hash;

  Long charIndex = (long)(charset.indexOf(s.charAt(0)));
  if(charIndex == -1)
    return hash;

  for(int i = 1 ; i < n; i++)
    hash += (long)(charIndex * Math.pow(charset.length(), i));

  hash += charIndex + 1 + orderedHash(s.substring(1), charset, n - 1);

  return hash;
}
如果需要更高的精度,例如使用无符号类型或由两个long组成的复合类型,并使用子字符串计算hashcode

编辑:虽然前面的算法已经足够我使用了,但我注意到如果字符串的长度没有比所选的
n
大,那么它实际上并没有正确排序字符串。有了这个新算法,现在应该可以了。
orderedHash("a", charset, 13)              // 1
orderedHash("abc", charset, 13)            // 4110785825426312
orderedHash("b", charset, 13)              // 99246114928149464
orderedHash("google", charset, 13)         // 651008600709057847
orderedHash("stackoverflow", charset, 13)  // 1858969664686174756
orderedHash("stackunderflow", charset, 13) // 1858969712216171093
orderedHash("stackunderflo", charset, 13)  // 1858969712216171093 same, 13 chars limitation 
orderedHash("z", charset, 13)              // 2481152873203736576
orderedHash("zzzzzzzzzzzzz", charset, 13)  // 2580398988131886038
orderedHash("zzzzzzzzzzzzzz", charset, 14) // -4161820175519153195 no good, overflow
orderedHash("ZZZZZZZZZZZZZ", charset, 13)  // 0 no good, not in charset