免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: starwing83
打印 上一主题 下一主题

数据结构?哈希表和红黑树对字符串键,哪个快? [复制链接]

论坛徽章:
0
21 [报告]
发表于 2012-07-02 10:12 |只看该作者
本帖最后由 wwwsq 于 2012-07-02 10:31 编辑
egmkang 发表于 2012-07-01 16:53
数量小的话,用谁都一样,搞不好数组都可以.
数据量大的话,hash会快很多,如果你的hash函数足够好的话:mr ...



哈希函数都差别不大,包括最近很火的murmur-hash,也只有特定场景才会略快一些。
如果是做比较通用的哈希表,各种哈希算法差别是不大的。

影响哈希表性能的因素主要是bucket的个数,以及哈希表本身的结构。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
22 [报告]
发表于 2012-07-02 12:04 |只看该作者
本帖最后由 yulihua49 于 2012-07-02 12:10 编辑
starwing83 发表于 2012-06-28 16:32
回复 15# yulihua49

rbtree再小也比hash慢(比较次数多),假定你的hash函数足够好。
只有一个元素时,二者一样。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
23 [报告]
发表于 2012-07-02 12:07 |只看该作者
wwwsq 发表于 2012-07-02 10:12
哈希函数都差别不大,包括最近很火的murmur-hash,也只有特定场景才会略快一些。
如果是做比较通用的 ...

人家说是跟树比。
如果不同的hash方法,除了算法本身的速度,hash冲突的影响更大。

论坛徽章:
0
24 [报告]
发表于 2012-07-02 13:30 |只看该作者
本帖最后由 wwwsq 于 2012-07-02 13:36 编辑
yulihua49 发表于 2012-07-02 12:07
人家说是跟树比。
如果不同的hash方法,除了算法本身的速度,hash冲突的影响更大。



“数据量大的话,hash会快很多”,这句话也是不准确的。无论数据多少,hash表都比rbtree快。

你看看2的乘方就知道了,64个元素的表,二叉树也要比较六次。比较六次就意味着要去六个随机内存地址取内容。虽然会有cpu预读之类的机制,但是还是会有损失。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
25 [报告]
发表于 2012-07-02 14:28 |只看该作者
本帖最后由 yulihua49 于 2012-07-02 14:56 编辑
wwwsq 发表于 2012-07-02 13:30
“数据量大的话,hash会快很多”,这句话也是不准确的。无论数据多少,hash表都比rbtree快。

你看看 ...

数据量大的话,hash会快很多--不是我说的。不过也是可以理解的。hash接近常数,而rbtree在数据量大的时候时间比较长,所以有那谁谁谁的结论。

其他--同意你的意见。

我们的项目需要对内存的各种数据进行检索,有大数据,也有小数据。
我们使用hash表,也使用AVL树。至于使用哪一种,并不取决于数据量的大小,一般都是使用hash表。只有:
当数据是动态的,即在使用过程中会增加一些或减少一些数据的场合,或:
需要对key进行不等比较时(小于,小于等于,大于,大于等于)才使用AVL树。

我们的实际情况,在100000级数据量下,hash的检索时间通常<0.1微秒,而AVL树则需要1.8微秒左右。给各位一个数量级方面的概念。

二叉树:
当仅使用二叉树排序时(建立,遍历,删除,并不用于检索),或对树的内容经常进行调整时,rbtree是最快的。
但是需要大量检索时,应该AVL树最合适。
所以我认为STL map使用AVL树更合适些。

论坛徽章:
0
26 [报告]
发表于 2012-07-02 15:10 |只看该作者
本帖最后由 wwwsq 于 2012-07-02 15:14 编辑
yulihua49 发表于 2012-07-02 14:28
数据量大的话,hash会快很多--不是我说的。不过也是可以理解的。hash接近常数,而rbtree在数据量大的时候时 ...



“而rbtree在数据量大的时候时间比较长”,这句话是人云亦云。这多半是做性能测试做出来的结论。因为数据少的时候,数据都可以被cpu给cache住。所以那些人得出了这个似是而非的结论。
实际上在真实环境里面,不论数据多少,就算只有八条数据,二叉树也要三次随机内存读取,肯定是低效的。


AVL和红黑树各有特点,很难说哪个更好了。所以在STL之外,各种容器和数据结构还是毛多毛多的啊。。。。
要想用的爽,在特定的场合是要自己写数据结构的。不过这种场景不常见,一般来说STL就够了。

论坛徽章:
0
27 [报告]
发表于 2012-07-02 15:19 |只看该作者
本帖最后由 hbmhalley 于 2012-07-02 15:21 编辑
starwing83 发表于 2012-06-28 16:32
回复 15# yulihua49
我是比较担心在数量级较小的情况下,红黑反而会快。就比如插入排序在排序元素少于16个的情况下比快排快一样。

对啊,解决哈希冲突的过程不就像小数量级的插入排序么,rbtree才是类似快排. 比反了.

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
28 [报告]
发表于 2012-07-02 15:32 |只看该作者
本帖最后由 yulihua49 于 2012-07-02 15:47 编辑
hbmhalley 发表于 2012-07-02 15:19
对啊,解决哈希冲突的过程不就像小数量级的插入排序么,rbtree才是类似快排. 比反了.

前边已经说了,你不必担心,一般情况就hash吧,不会有错。
除非。。。。。。。。。

hash冲突是在建hash表时处理的,不太影响后边的检索时间。
当然,冲突严重时是影响检索性能的。
所以你需要寻找一下对你来说较好的hash方法,减少冲突。

我们十来个元素就用hash了,如果检索频繁,能看到明显的效果。再少就顺序了。

数据量极少时讨论各种检索算法的性能,没意义吧?

我们也不是明知只有几条记录也弄个hash。只不过知道这个表数据量不大,几十上百的规模,但是查询频繁。就弄个hash,结果有时就几条,甚至1条记录,也就那么的了,不考察性能了。到底谁好谁不好,没意义。

论坛徽章:
0
29 [报告]
发表于 2012-07-02 17:29 |只看该作者
单词有500个的话, 用多叉树可能最快
  struct Mtree
  {
     int value
     Mtree *child[128];
  };

  原因是多叉树最坏情形需要25次数值比较和指针操作.
  平均情形可能会 < 5次(看你的数据集了)

  hash的话光算hash值就需要25个数值操作(乘法), 后面是一个常数次的指针操作和数值比较.
  
单词有100万个, 可能多叉树就放不下了, hash会比各种树快, 原因是这是个典型的静态hash表
  查找问题. hash表的建立和查找都比树快.

单词有5000万个, 动态hash可能就建立补起来了, 平衡树可以建立起来.

单词有5亿个, 可能要多加4台机器, hash开, 还是hash

论坛徽章:
0
30 [报告]
发表于 2012-07-02 17:33 |只看该作者
yulihua49 发表于 2012-07-02 15:32
前边已经说了,你不必担心,一般情况就hash吧,不会有错。
除非。。。。。。。。。



hash表最大的缺陷是当数据的量难以估计的时候,没法设置合适的bucket值。
元素可能是10个,也可能是10000个,那么hash表怎么初始化bucket个数。

这里有几种思路:
1,设置缺省的起始bucket个数为100左右,然后让hash表自动扩容。缺点是扩容的时候性能要受影响。
2,结合业务,每次给10000的bucket。缺点是浪费内存,而且无法处理100w这种极端情况。
3,把hash表的list变成哈希表。缺点是结构复杂,多次哈希速度慢。

综合来看,方案1是比较好的折中。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP