所以我一直在阅读Hashing的期末考试,而我似乎无法理解正在发生的事情。有人能向他解释Hashing他们理解它的最佳方式吗?
对于这个模糊的问题感到抱歉,但我希望你们能够说“哈希是什么”,所以我至少要有一个开始,如果有人知道任何有用的方法来理解它,那也会有所帮助
答案 0 :(得分:4)
哈希是一种快速启发式方法,用于查找对象的等价类。
用更小的词来说:
散列很有用,因为它在计算上很便宜。成本与等价类的大小无关。 http://en.wikipedia.org/wiki/Time_complexity#Constant_time
等价类是一组等价的项。想想数字的字符串表示。您可能会说“042”,“42”,“42.0”,“84/2”,“41.9 ......”是相同基础抽象概念的等效表示。他们将处于同一等级阶层。 http://en.wikipedia.org/wiki/Equivalence_class
如果我想知道“042”和“84/2”是否等价,我可以计算每个(一个便宜的操作)的哈希码,并且只有当哈希码相等时,我才会尝试更昂贵的检查。如果我想将数字的表示划分为桶,那么相同数字的表示在桶中,我可以通过哈希码选择桶。
哈希是启发式,即它并不总能产生完美的结果,但是它的缺陷可以由知道它们的算法设计者来缓解。散列产生哈希码。两个不同的对象(不在同一个等价类中)可以生成相同的哈希代码,但通常不会,但同一个等价类中的两个对象必须生成相同的哈希代码。 http://en.wikipedia.org/wiki/Heuristic#Computer_science
答案 1 :(得分:3)
Hashing正在总结。
数字序列(2,3,4,5,6)的散列是这些数字的摘要。例如,图20是一种不完整地包括原始数据中的所有可用位的摘要。这不是一个很好的总结,但它是一个总结。
当值涉及多个字节的数据时,某些位必须被拒绝。如果你使用sum和mod(例如,将总和保持在20亿以下),你往往会保留很多最右边的位并丢失所有最左边的位。
所以好的哈希是公平的 - 它公平地保留和拒绝比特。这往往可以防止碰撞。
例如,我们简单化的“和散列”将在其他数字序列之间发生碰撞,这些数字碰巧也会有相同的总和。答案 2 :(得分:1)
你可以确定性地获取一些数据,单向计算一些固定长度的数据,当你稍微改变输入时,它会完全改变。
答案 3 :(得分:1)
应用于某些数据的哈希函数会生成一些新数据。 对于相同的数据,它始终是相同的。 这就是它。
经常放在它上面的另一个约束,我认为并非如此,散列函数要求你不能从散列中得出原始数据。 对我来说,这是一个自己的类别,称为加密或单向散列。
对某些类型的哈希函数有很多要求
例如,散列的长度始终相同。
或哈希值随机分配给任何给定的输入数据序列。
唯一重要的一点是它的确定性(对于相同的数据总是相同的哈希)。
因此您可以使用它来验证数据完整性,验证密码等。
在这里阅读所有相关内容
答案 4 :(得分:1)
您应首先阅读wikipedia article。然后就你不理解的主题提出问题。
简而言之,引用文章,哈希意味着:
切碎和混合
也就是说,给定一个值,你可以得到另一个(通常)更短的值( chop ),但是即使原始值的一小部分发生变化,所获得的值也应该改变(混合强>)。
让我们以x % 9
为例说明散列函数。
345 % 9 = 3
355 % 9 = 4
344 % 9 = 2
2345 % 9 = 5
您可以看到此散列方法会考虑输入的所有部分,并在任何数字发生变化时进行更改。这使它成为一个很好的散列函数。
另一方面,如果我们采取x%10
。我们会得到
345 % 10 = 5
355 % 10 = 5
344 % 10 = 4
2345 % 10 = 5
正如您所看到的,大多数散列值都是5
。这告诉我们x%10
是一个比x%9
更糟糕的散列函数。
请注意,x%10
仍然是哈希功能。身份函数也可以被认为是哈希函数。
答案 5 :(得分:1)
首先我们应该说一下Hashing算法要解决的问题。
假设您有一些数据(可能是数组,树或数据库条目)。您希望在此数据存储区中找到具体元素(例如在数组中),但速度要快得多。怎么做?
构建此数据存储区时,可以为每个项目计算特殊值(名为HashValue)。计算此值的方法可能不同。但是所有方法都应该满足特殊条件:每个项目的计算值应该是唯一的。
所以,现在你有一个项目数组,每个项目你有这个HashValue。如何使用它?考虑一下有N个元素的数组。我们根据他们的HashHalues将你的物品放到这个数组中。
假设您要回答这个问题:此数组中是否存在“it1”项?要回答它,您可以简单地找到“it1”的HashValue(让我们称之为f(“it1”))并查看f(“it1”)位置的数组。如果此位置的元素不为null(并且等于我们的“it1”项),我们的答案是正确的。否则回答是错误的。
还存在碰撞问题:如何找到这样最酷的函数,它将为所有不同的元素提供唯一的HashValues。实际上,这种功能不存在。有很多好的功能,可以给你很好的价值。
更好理解的一些例子:
假设您有一个字符串数组:A = {“aaa”,“bgb”,“eccc”,“dddsp”,...}。你要回答这个问题:这个数组是否包含字符串S?
首先,我们要选择计算HashValues的函数。让我们使用函数f,它具有这个意义 - 对于给定的字符串,它返回该字符串的长度(实际上,它是非常糟糕的函数。但是为了便于理解,我把它拿走了。)
所以,f(“aaa”)= 3,f(“qwerty”)= 6,等等......
现在我们要为数组A中的每个元素计算HashValues:f(“aaa”)= 3,f(“eccc”)= 4,...
让我们拿一个数组来保存这些项目(它也命名为HashTable) - 让我们称之为H(一个字符串数组)。所以,现在我们根据他们的HashValues将我们的元素放到这个数组中:
H [3] =“aaa”,H [4] =“eccc”,......
最后,如何在这个数组中找到给定的String?
假设您有一个String s =“eccc”。 f(“eccc”)= 4.所以,如果H [4] ==“eccc”,我们的答案将是真的,否则填写是假的。
但是如何避免情况,何时元素具有相同的HashValues?它有很多方法。其中之一:HashTable中的每个元素都包含一个项目列表。所以,H [4]将包含所有项目,HashValue等于4.以及如何找到具体元素?这很简单:计算此项HashValue并查看HashTable [HashValue]中的项目列表。如果其中一个项目等于我们的搜索元素,则答案为真,其中答案为假。
答案 6 :(得分:1)
我说linut的答案非常好,但我会稍微放大一点。计算机非常擅长访问数组中的东西。如果我知道某个项目在MyArray [19]中,我可以直接访问它。散列函数是将查找键映射到数组下标的一种方法。如果我在一个数组中存储了193,372个不同的字符串,并且我有一个函数将为其中一个字符串返回0,为另一个字符串返回1,为另一个字符串返回2,等等到最后一个为193,371,我可以看看是否有任何给定string在数组中运行该函数,然后查看给定的字符串是否与数组中该点中的字符串匹配。很好,很容易。
不幸的是,在实践中,事情很少是如此美好和整洁。虽然通常可以编写一个函数,将输入映射到一个很好的简单范围内的唯一整数(如果没有别的话:
if (inputstring == thefirststring) return 0; if (inputstring == thesecondstring) return 1; if (inputstring == thethirdstring) return 1; ... up to the the193371ndstring
在许多情况下,“完美”功能需要花费大量精力才能计算出不值得的努力。
相反,要做的是设计一个系统,其中哈希函数说明应该从哪里开始查找数据,然后使用其他方法从那里搜索数据。一些常见的方法是:
当处理固定数据集(例如编译器的关键字集)时,线性散列通常是好的;如果它工作不正常,可以调整哈希函数,以便它可以很好地工作。处理未知数据集时,链桶散列通常是最好的方法。处理额外列表的开销可能会使它比双重哈希更昂贵,但它的可能性要小得多。