关于Hash的作用

dracularking 2013-04-05 11:31:58
大家来说说就是设计出哈希函数的目的是什么,除了节约空间还有什么作用? 因为可以通过array,map或direct-address table
...全文
521 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
InphinitiZ 2013-09-21
  • 打赏
  • 举报
回复
引用 22 楼 dracularking 的回复:
[quote=引用 20 楼 sjlzcj 的回复:] C/C++ code?12345struct map{key;value;......} 这是一个简单的map结构,他最终在内存中的样子,我们可以理解为map[]; 这样一个数组 对于map[?]任何一个位置都是一个完整的map结构,我们要在这个数组中找到key,就是一个遍历 但hashmap 是在上面结构的基础上加了 hashcode 这样一个东西使得 map[k……
老实说,这个问题还真不该拿map与hash table比,你说的key value映射的map在实现上查找起来需要遍历没错 真正的比较双方是direct address table(就是数组)和hash table hash table的优势体现在: When the set K of keys stored in a dictionary is much smaller than the universe U of all possible keys, a hash table requires much less storage than a direct address table. 你之前说hash的优势是这样的: <<a["ABC".hash]="ABC" 这样子存完之后 想拿"ABC"呢 就是 a["ABC".hash],,所以通常我们<<处理大规模非线性 既然已经知道"ABC",还要a["ABC".hash]去取"ABC"?[/quote] a["ABC".hash]保存的可不止是"ABC"而已。。还有其它内容,比如保存的是一条用户记录的话那就还有其它和用户相关的信息 试想要在10亿个用户记录里找到一个名为"ABC"的用户的信息,你难道要遍历比较每一个记录看是不是名为"ABC"吗
dracularking 2013-04-10
  • 打赏
  • 举报
回复
引用 20 楼 sjlzcj 的回复:
C/C++ code?12345struct map{key;value;......} 这是一个简单的map结构,他最终在内存中的样子,我们可以理解为map[]; 这样一个数组 对于map[?]任何一个位置都是一个完整的map结构,我们要在这个数组中找到key,就是一个遍历 但hashmap 是在上面结构的基础上加了 hashcode 这样一个东西使得 map[k……
老实说,这个问题还真不该拿map与hash table比,你说的key value映射的map在实现上查找起来需要遍历没错 真正的比较双方是direct address table(就是数组)和hash table hash table的优势体现在: When the set K of keys stored in a dictionary is much smaller than the universe U of all possible keys, a hash table requires much less storage than a direct address table. 你之前说hash的优势是这样的: <<a["ABC".hash]="ABC" 这样子存完之后 想拿"ABC"呢 就是 a["ABC".hash],,所以通常我们<<处理大规模非线性 既然已经知道"ABC",还要a["ABC".hash]去取"ABC"?
dracularking 2013-04-10
  • 打赏
  • 举报
回复
引用 19 楼 sjlzcj 的回复:
引用 18 楼 dracularking 的回复:你说得没错,在这种情形下因为hash与数组下标有映射关系所以不需要遍历 但这个本身就不是平等的对比,我之前也说过的,这里强调的是hash具有“映射”功能,但我想这不是hash最主要的目的,如果想要映射,map这种数据结构也可以做到,你说是不是? map只是一种K-V的数据结构,懂?它最终落地还是要在一个一维数组……
你的意思就是只有数字型的key才可以不需要遍历直接对应到其value?(数组下标和数组内容的映射可以看成是数字型的key和其value的映射) 数字和字符串对计算机来说有本质的区别吗? 为什么数字就能直接查找呢?
dracularking 2013-04-09
  • 打赏
  • 举报
回复
引用 17 楼 sjlzcj 的回复:
如果 a[50]="ABC";如果说常规方法 找到 ABC 要遍历 到a[50] 而 hash 呢 假设 "ABC".hash=50 a["ABC".hash]="ABC" 这样子存完之后 想拿"ABC"呢 就是 a["ABC".hash],,所以通常我们处理大规模非线性 的数据的时候 hash 是一种解决思路
你说得没错,在这种情形下因为hash与数组下标有映射关系所以不需要遍历 但这个本身就不是平等的对比,我之前也说过的,这里强调的是hash具有“映射”功能,但我想这不是hash最主要的目的,如果想要映射,map这种数据结构也可以做到,你说是不是? 具体的点在16楼
sjlzcj 2013-04-09
  • 打赏
  • 举报
回复

struct map{
key;
value;
......
}
这是一个简单的map结构,他最终在内存中的样子,我们可以理解为map[]; 这样一个数组 对于map[?]任何一个位置都是一个完整的map结构,我们要在这个数组中找到key,就是一个遍历 但hashmap 是在上面结构的基础上加了 hashcode 这样一个东西使得 map[key.hashcode]= mapObject(无hash冲突) 也就是说 map 是定义了一种 K-V 的数据结构,,而hash是用来大规模非线性的数据查找的问题的
sjlzcj 2013-04-09
  • 打赏
  • 举报
回复
引用 18 楼 dracularking 的回复:
你说得没错,在这种情形下因为hash与数组下标有映射关系所以不需要遍历 但这个本身就不是平等的对比,我之前也说过的,这里强调的是hash具有“映射”功能,但我想这不是hash最主要的目的,如果想要映射,map这种数据结构也可以做到,你说是不是?
map只是一种K-V的数据结构,懂?它最终落地还是要在一个一维数组中(这里用一维数组全权代理内容了) 你map是可以通过 key 来找到value 但除了 hashMap外 其他的不是用hash的map 来定位key的过程依然是个一个遍历,,即使hashmap在hash冲突的时候也会出现小范围的遍历
sjlzcj 2013-04-08
  • 打赏
  • 举报
回复
引用 15 楼 dracularking 的回复:
很高兴见到你的回复 说得很不错, hash可以用来定位没错,但是不用hash就不能定位了?如果说需要遍历,那hash就不要遍历了?不都是数据吗,这种定位是直接寻址的
没错 hash就不要遍历了 因为hash出来的结果就是数组的下标 举个例子 有一个String[100] a; 如果 a[50]="ABC";如果说常规方法 找到 ABC 要遍历 到a[50] 而 hash 呢 假设 "ABC".hash=50 a["ABC".hash]="ABC" 这样子存完之后 想拿"ABC"呢 就是 a["ABC".hash],,所以通常我们处理大规模非线性 的数据的时候 hash 是一种解决思路 上边的例子不考虑hash冲突,Java中的hashmap 对hash冲突的解决办法是链表 所以 如果使用hashmap的时候 key的hashcode很糟糕很容易产生重复的话,会及其影响性能 可以定义2个key 一个hashcode return 1; 一个用java默认的 分别创建10000个实例用来当做hashmap的key 比较一下2个map的遍历时间
dracularking 2013-04-08
  • 打赏
  • 举报
回复
关于hash,算法导论中有阐述



但关键这句话怎么理解:When the set K of keys stored in a dictionary is much smaller than the universe U of all possible keys, a hash table requires much less storage than a direct address table.

为什么当set K远小于U时,direct address table就不能节省空间,和动态静态有关?
dracularking 2013-04-07
  • 打赏
  • 举报
回复
引用 14 楼 sjlzcj 的回复:
以下都是个人观点 首先hash的结果不是用来比较大小用的,,而是用来定位的 因为现在的内存是线性存储的,所以我们可以用一个很大的数组来比作内存,从而无论什么样的数据结构最终都落在了一维数组中 我们在一个很大的一维数组中来找到一个想要的数据,就只能遍历了,不要说下标拿取,及时下标拿取,我们还需要另一个数组来记录着下标,在另一个数组中找到对应的下标值的过程也……
很高兴见到你的回复 说得很不错, hash可以用来定位没错,但是不用hash就不能定位了?如果说需要遍历,那hash就不要遍历了?不都是数据吗,这种定位是直接寻址的
Inhibitory 2013-04-06
  • 打赏
  • 举报
回复
引用 4 楼 dracularking 的回复:
引用 3 楼 ilyysys 的回复:通过Hash值可以初步定位元素在数组中的位置,提高查询效率 如果用map的数据结构,不是也可以高效的定位?
Hash与Map并不矛盾,Map有多种存储方式,使用TreeMap,HashMap, LinkedHashMap等。 Hash是用一个Key快速计算出存储位置,记忆的是Key,而Array需要记忆的是下标0,1,2,3,....,完全不是一个概念。
sjlzcj 2013-04-06
  • 打赏
  • 举报
回复
以下都是个人观点 首先hash的结果不是用来比较大小用的,,而是用来定位的 因为现在的内存是线性存储的,所以我们可以用一个很大的数组来比作内存,从而无论什么样的数据结构最终都落在了一维数组中 我们在一个很大的一维数组中来找到一个想要的数据,就只能遍历了,不要说下标拿取,及时下标拿取,我们还需要另一个数组来记录着下标,在另一个数组中找到对应的下标值的过程也是一个遍历。 从而我们思考有没有什么别办法可以很快的定位的需要的数据呢? 数组的下标都是由数字组成的,那么我们有没有办法将数据与下标关联起来呢? 如果说我们找出一种算法,使得任何数据都可以运算出一个整数,且整数在0到N之间,那不就关联起来了。 很幸运我们找到了这样的算法,又由于该算法将数据分散的放在了数组之中,数据彼此间没有什么明确的关系,形同散列一样,所以我们就给这算法叫hash(散列)吧。。 哈哈,,,
dracularking 2013-04-06
  • 打赏
  • 举报
回复
引用 3 楼 ilyysys 的回复:
通过Hash值可以初步定位元素在数组中的位置,提高查询效率
如果用map的数据结构,不是也可以高效的定位?
噢噢噢噢 2013-04-06
  • 打赏
  • 举报
回复
通过Hash值可以初步定位元素在数组中的位置,提高查询效率
dracularking 2013-04-06
  • 打赏
  • 举报
回复
引用 11 楼 Inhibitory 的回复:
引用 8 楼 dracularking 的回复:key可以是任意的,不局限于0,1,2,3,....,这种情形下hash又有什么优势呢? 例如你要存储一些用户数据,key是用户名,value是用户的所有数据,如果这个时候用0, 1, 2, 等整数记肯定不方便,如果用用户名就会很方便。
你是说这时候采用hash化的方案是不适合的? 方便是针对人而言的?但是使用hash也不需要记0,1,2
dracularking 2013-04-06
  • 打赏
  • 举报
回复
引用 1 楼 Inhibitory 的回复:
Java code?1除了节约空间还有什么作用? hash可不节约空间,反而使用的是空间换时间。 差不多是常量时间内查找。
怎么说呢,如果不使用hash,array也是常量时间查找,但它们区别是什么? 使用hash的场合是和不使用hash的场合相对比的 如果不使用hash,所有可能的元素都要进行映射,但有些可能不需要映射,因为未必用到,使用hash就可以避免这种情况(这里可能有考虑不周到的地方)
dracularking 2013-04-06
  • 打赏
  • 举报
回复
引用 10 楼 fangmingshijie 的回复:
是的,简化应该是它设计的一个原因。 就像你说的,图像也可以数据化,但是图像数据化后,排序或者比较,就没有那么简单了,可能会相当的复杂。效率可能就会比较低。
但是简化(hash化)也是有代价的,而且简化后和原来的数据未必是一一映射,还需要另外引入数组,把这些代价综合考虑进去的话,是不是合算呢?当然可能是各取所需,时空转换,这个先不说。 比如假设原来的数据是 10000,10001, 10002 hash化后, f(10000) = 1 f(10001) = 2 f(10002) = 3 10000,10001, 10002之间的比较是不是一定比1,2,3之间的比较低效呢? 当然这可能只是个特例,如果原数据是 aaabbbccc, efghabebm, woieojlip 它们之间的直接比较可能比较低效,需要累加各自母权值(假设是这种计算方式) 但是hash化后再比也是经历这个计算过程的,最后总代价不是没变吗?因为每次比较都要重新计算hash值,这个计算的代价貌似并没有节约。
Inhibitory 2013-04-06
  • 打赏
  • 举报
回复
引用 8 楼 dracularking 的回复:
key可以是任意的,不局限于0,1,2,3,....,这种情形下hash又有什么优势呢?
例如你要存储一些用户数据,key是用户名,value是用户的所有数据,如果这个时候用0, 1, 2, 等整数记肯定不方便,如果用用户名就会很方便。
  • 打赏
  • 举报
回复
是的,简化应该是它设计的一个原因。 就像你说的,图像也可以数据化,但是图像数据化后,排序或者比较,就没有那么简单了,可能会相当的复杂。效率可能就会比较低。
dracularking 2013-04-06
  • 打赏
  • 举报
回复
引用 7 楼 fangmingshijie 的回复:
hash的产生有这样一种背景——有些数据本身是无法排序的(如图像),有些数据是很难比较的(如图像)。如果数据本身是无法排序的,就不能对它们进行比较查找。如果数据是很难比较的,即使采用折半查找,要比较的次数也是非常多的。因此,哈希查找并不查找数据本身,而是先将数据映射为一个整数(它的哈希值),并将哈希值相同的数据存放在同一个位置一即以哈希值为索引构造一个数组。 在……
谢谢,这样说的话,设计hash其中一个原因是出于简化的考虑?因为我认为既然是数据,就可以排序和比较,即使是图像,因为图像可以数据化。
dracularking 2013-04-06
  • 打赏
  • 举报
回复
引用 5 楼 Inhibitory 的回复:
引用 4 楼 dracularking 的回复:引用 3 楼 ilyysys 的回复:通过Hash值可以初步定位元素在数组中的位置,提高查询效率 如果用map的数据结构,不是也可以高效的定位? Hash与Map并不矛盾,Map有多种存储方式,使用TreeMap,HashMap, LinkedHashMap等。 Hash是用一个Key快速计算出存储位置,记忆的是Key……
是的,不矛盾,从Hash和Map的结合可见一斑 但这里的重点是Map也可以不通过hash换算index的方式来进行映射,通过key映射value的方式,key可以是任意的,不局限于0,1,2,3,....,这种情形下hash又有什么优势呢?(希望不介意讨论,原谅我有点钻牛角尖
加载更多回复(3)

50,544

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧