First we try, then we trust

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  183 随笔 :: 111 文章 :: 2983 评论 :: 339 引用
自从《华容道与数据结构》系列文章写完后,有很多热心的朋友提出了宝贵的意见,使得华容道程序的运行效率不断提升。在这里特别感谢“智能算法爱好者”与sumtec,给程序提出了很多宝贵的意见。

Sumtec指出:“AVLTree是否可以用HashTable来替代,毕竟你的目的不是要排序,而是要检验是否容易产生重复。从纯粹的理论上来说,HashTable在这方面的性能消耗应该比AVLTree要好一些,因为AVLTree的复杂度至少是O(Log2(x))级别的,而HashTable则接近于O(C)级别的。”,因此我将程序重新进行了调整,目的是:在不考虑内存使用的情况下再次提高系统执行效率。

我的修改包括两部分:1、用HashTable取代AVLTree,设计并实现自己的HashCode算法。2、修改华容道布局表示方式,从原来的4字节表示改为8字节表示,这么做可以省略掉原有程序中的排序操作。

经过修改后,每个节点平均比较3~5次便可知道是否有重复,接近于O(C)级别。Int64的布局表示省掉了排序,效率进一步提升。但内存占用总体要增加(以内存换效率)。

现在,原有系统中第四个布局的求解时间从最初的6.67秒降到了消除Execption影响后的1.55秒,现在又降到了使用HashTable的0.90秒。贴张图上来:



源代码我会随后放上来,并且进一步完善《华容道与数据结构》系列,这次的重点放在HashTable上面。
posted on 2005-02-20 17:02 吕震宇 阅读(5788) 评论(8)  编辑 收藏

评论

Unit Test中的所有Console的Output去掉,估计只需要0.5秒甚至更加少。
  回复  引用  查看    

#2楼 [楼主] 2005-02-20 18:08 吕震宇      
效率没有那么高的提升,去掉Console命令后,程序执行时间是0.78秒:)
  回复  引用  查看    

#3楼  2005-02-20 19:15 sumtec      
嗬嗬,你是不是用.NET的HashTable?另外你说的“自己的HashCode算法”是不是指重写了HashCode属性?如果我没有记错的话,HashTable的效率主要取决于抗冲突能力,HashCode相对少为次要一点。对HashCode的要求就是尽可能均匀分布,事实上对于你原来的4Byte版本,这个值本身就是HashCode,因此也可以认为比较接近于均匀分布,也就差不多了。

所以如果我来调优的话,可能不会首先在这个上面花太大的精力。现在看来调整算法可能更有效果,比如说双向广优是否有可能?(当然,这个有点难度,尤其在可接受结果并非唯一的情况下,不过也不一定就不行。)或者更好的剪枝?

嗬嗬,你这个系列可以作为一个完整的例子了,可以讲解深优广优,AVLTree和HashTable,设计模式等等,一步步的讲解肯定很有趣。
  回复  引用  查看    

#4楼 [楼主] 2005-02-20 19:40 吕震宇      
@Sumtec

我在设计4Byte版本时,曾经考虑使用《编程珠玑》一书开篇例子的算法。但是那个例子仅仅是7位整数,所以使用HashTable(虽然书上不叫这个,但与HashTable的思想很相近)很有效率。可在这个4Byte版本中有2^32种变化,用直接使用HashTable几乎是不可能的。

另外,.net提供的HashTable是名、值对,究竟Hash得怎么样我心理没有底。所以我自己实现了自己的HashTable数据结构,并覆写了GetHashCode方法。虽然不能做到均匀分布,但效果还不错。我会在后面文章中写出算法和测试结果。基本思想是基于质数相乘累加的分解上(没有任何数学上的证明,仅仅凭感觉。因为公钥算法基本上基于两质数相乘分解唯一的理论上,我加了个累加)。这样HashTable的大小控制在40000左右,某HashCode下最多16个节点(复杂布局),但非常少,只有1~3个。绝大多数集中在一个HashCode对应1~6个节点。

  回复  引用  查看    

#5楼 [楼主] 2005-02-20 19:58 吕震宇      
@Sumtec

你所说的“双向广优”究竟如何操作呢?我理解是否从条件和结果两个方向查找。就像钻山洞从两个方向打通?

这个华容道的例子正式我这学期讲数据结构要用到的一个“关键”例子。希望大家多提建议,多出思路!
  回复  引用  查看    

#6楼  2005-02-21 20:56 sumtec      
关于HashTable的问题,我可能有些地方还是没有说清楚,年代久远,我也要翻翻资料复习一下才能够想起来了。不过就这个数据而言,我估计跟标准的HashTable有性能上的差距。这个还是稍后再来说吧。

双向广有的确如你所说的那样,从两个方向来查找。因为对于广优来说,就像在画一个金字塔,如果层数越深,其宽度就越大。因此对于广优来说,要提高性能无非从下面这两个角度去考虑:1、约束每一层向下一层发展的趋势,也就是限制宽度;2、约束探索的层数。

对于前者来说很明显就是“剪枝”,向你前面所说的“排除重复”就属于这一类的。对于后者来说,最优解的层数肯定不是随意志转移的,但是由于广优的求解过程如同画金字塔,那么画两座高为h的金字塔,其总面积明显比画一座高为2h的金字塔要小得多。

不过对于你这样的问题来说,不一定能够使用这种方式,我只是随口说说,没有仔细考虑。
  回复  引用  查看    

#7楼 [楼主] 2005-02-21 21:37 吕震宇      
@Sumtec

双向广优似乎实施会出现一些问题,因为只知道结果中曹操的位置,而其它棋子的位置并不能确定,也就是结果可能不只有一个,也就无从“双向”。

另外从实际结果的数据来看,并不是象想象中的金字塔模式。因为有重复布局判断、剪枝操作,所以总体来看树型结构更象葫芦。有时候某一层级可能在达到几百布局后又收缩到几十个布局,往复两到三次。

今天对程序又做了些调整,目的是找出我的HashTable设计相对AVLTree究竟提高了多少效率(消除排序带来的性能影响后再进行比较)。发现HashTable对性能有所提升,但不大,大概平均0.05秒左右。
  回复  引用  查看    

#8楼  2007-02-21 18:15 U2U      
哈哈,可喜的进步。6s -> 0.9s
  回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: