1、abp竞赛之文本文件词频查询 优化报告abp竞赛之文本文件词频查询 优化报告HouSisongGMail. 2007.03.15comtag:abp,单词统计,比赛,hash,速度优化,优化报告摘要: 以前参加过几次abp论坛的比赛(现在的其中的一个竞赛的题目是文本文件词频查询,本文章把自己的参赛代码的优化的思路整理出来;很多时候优化后的版本最高达到了STL实现版本的20倍!(2007.04.09 确认从MFC移植过来的时候引入了一个bug,“FILE* file=fopen(argv1,r); ”应该为“FILE* file=fopen(argv1,rb); ” 找了我好久:(谢谢hf141
2、4 !)(2007.03.17修正一个在vc2005编译器下访问vector的bug,将代码“TNode* end=&(_vbase_hash_power); ” 改为 “base_t:iterator end=_vbase.end();” ) (abp现在还能够访问(只读),会员很多都“搬迁”到了 :)文本文件词频查询 竞赛要求:OS:Windows2000/XPCompiler:VC6/VC.net/VC.net2003评判标准:正确性+速度截止时间:2003年10月11日前(含)方法:每个人可以多次提交。每次提交完了,我会告诉你你的成绩和最快的人的成绩。内容:一个文件,仅由大小写字母,空
3、格和换行符组成。我们称一个词为连续的大小写字符,两边是空格或者文件头/尾。词大小写敏感。某个词的词频是这个词在这个文件里面出现的次数。要求,输入一个文件(至少有一个词,并且最大词频的词只有一个),输出那个词频最大的词。譬如,输入:aaabbbcccdddaaa输出:aaa补充一句:文件可能非常大。(xxxM,xG)还有就是,文件中不会出现TAB。(测试程序的时候,我们将vc目录中的源代码文件合成了一个数据文件来作为测试数据)一个“标准”C+实现版本: (可以作为一个STL使用的实例:)#pragmawarning(disable:4786)#include#include#include#in
4、clude#includeusingnamespacestd;intmain(intargc,char*argv)/assert(argc=2);clock_tstart=clock();constchar*file_name=argv1;ifstreamin_file(file_name);mapword_table;stringmax_word;longmax_count=0;stringword;while(in_fileword) long old_count_inc=(+word_tableword); if(old_count_incmax_count) max_word=word
5、; max_count=old_count_inc; coutWord:max_wordCount:max_countendl;coutSeconds=(double)(clock()-start)/CLOCKS_PER_SEC)endl;return0;我用的测试编译器vc6.0 , CPU赛扬2.0G下面的代码很多时候速度是上面的版本的20倍,源代码如下(优化说明在代码之后);(我以前提交的代码使用了MFC库,为了容易编译和理解,我做了一些代码调整,去除MFC依赖,把一个复杂的代码循环展开删除了,可能慢了10%)#pragmawarning(disable:4786)#include#in
6、clude#include#include#include#includenamespaceclassCMyAllotenumchunk_size=1024*256;/块大小char*_cur;char*_end;std:vector_vector;void*_new_else(unsignedintsize);public:CMyAllot():_end(0),_cur(0)virtualCMyAllot()if(!_vector.empty()DelAll();inlinevoid*_fastcallNew(unsignedintsize)size=(size+3)22);/4字节边界对齐
7、if(int)size(_end-_cur)/够用char*result=_cur;_cur+=size;returnresult;else/不够用return_new_else(size);voidDelAll()for(inti=0;i(chunk_size2)/不够用,而且需要的空间较大char*result=newcharsize;char*old_back=_vector.back();_vector_vector.size()-1=result;_vector.push_back(old_back);returnresult;else/不够用,开辟新的空间char*result=n
8、ewcharchunk_size;_cur=result+size;_end=result+chunk_size;_vector.push_back(result);returnresult;structTNode/hash表使用的节点类型(链表)TNode*pNext;unsignedintcount;charstr1;/不一定只有一个字节,会根据字符串分配空间structTComp/返回时的排序准则booloperator()(constTNode*l,constTNode*r)if(l-count)=(r-count)returnstd:string(&l-str0)str0);else
9、return(l-count)(r-count);inlineunsignedint_fastcallhash_value(char*begin,char*end)unsignedintresult=0;doresult=5*result+(*begin);/利用asm:leareg0,reg1*4+reg1,并且5是质数while(+begin)!=end);returnresult;inlineunsignedint_fastcallhash_value(char*pstr)unsignedintresult=0;doresult=5*result+(*pstr);/利用asm:leare
10、g0,reg1*4+reg1,并且5是质数while(*(+pstr);returnresult;/测试字符串是否相同,如果需要不区分大小写,修改这个函数和hash函数就可以了inlinebool_fastcalltest_str_EQ(char*begin,char*end,char*str)/for(;begin!=end;+begin,+str)/if(*begin)!=*(str)returnfalse;doif(*begin)!=*(str)returnfalse;+begin;+str;while(begin!=end);returntrue;classCHashSettypede
11、fstd:vectorbase_t;inlineunsignedinthash_index(char*begin,char*end)constreturnhash_value(begin,end)&(_hash_mask);inlineunsignedinthash_index(char*pstr)constreturnhash_value(pstr)&(_hash_mask);voidresize();void_fastcallmove_insert(base_t&v,TNode*pOldNode)const;TNode*_fastcallNewNode(char*begin,char*en
12、d);voidSort(base_t&v,unsignedintsortCount);unsignedint_hash_power;unsignedint_hash_mask;unsignedint_node_count;base_t_vbase;CMyAllot_allot;void_fastcallelse_insert(TNode*pNode,char*begin,char*end);public:CHashSet();virtualCHashSet();unsignedintsize()constreturn_node_count;unsignedintsum();void_fastc
13、allinsert(char*begin,char*end);voidGetStrList(std:ostream&cout,unsignedintsortCount);CHashSet:CHashSet():_hash_power(2),_vbase(unsignedint)(_hash_power),(TNode*)0)/注意次序_node_count=0;_hash_mask=_hash_power-1;/_hash_power=10)base_t:iteratorend=_vbase.end();for(base_t:iteratori=_vbase.begin();icount;pN
14、ode=pNode-pNext;returnsum;void_fastcallCHashSet:insert(char*begin,char*end)unsignedintindex=hash_index(begin,end);TNode*pNode=_vbaseindex;if(!pNode)/节点还没有使用_vbaseindex=NewNode(begin,end);+_node_count;elseif(test_str_EQ(begin,end,pNode-str)/累加+(pNode-count);elseelse_insert(pNode,begin,end);void_fastc
15、allCHashSet:else_insert(TNode*pNode,char*begin,char*end)while(true)if(!(pNode-pNext)pNode-pNext=NewNode(begin,end);+_node_count;if(_node_count=(_hash_power)resize();break;elseif(test_str_EQ(begin,end,pNode-pNext-str)+(pNode-pNext-count);break;pNode=pNode-pNext;void_fastcallCHashSet:move_insert(base_
16、t&v,TNode*pOldNode)constTNode*&pNode=vhash_index(pOldNode-str);pOldNode-pNext=0;if(!pNode)/节点还没有使用pNode=pOldNode;elseif(!pNode-pNext)pNode-pNext=pOldNode;elseTNode*pListNode=pNode-pNext;while(pListNode-pNext!=0)pListNode=pListNode-pNext;pListNode-pNext=pOldNode;TNode*_fastcallCHashSet:NewNode(char*b
17、egin,char*end)TNode*pNode=(TNode*)(_allot.New(sizeof(TNode)+end-begin);pNode-pNext=0;pNode-count=1;char*i=pNode-str;/for(;begin!=end;+i,+begin)/(*i)=(*begin);do(*i)=(*begin);+i,+begin;while(begin!=end);(*i)=char(0);returnpNode;voidCHashSet:resize()if(_node_count=(_hash_power)base_t:iteratorend=_vbas
18、e.end();_hash_powerpNext;move_insert(new_vbase,pNode);pNode=temp;_vbase.swap(new_vbase);/voidCHashSet:Sort(base_t&v,unsignedintsortCount)if(sortCount=1)v.resize(1);base_t:iteratorend=_vbase.end();TNode*maxNode=_vbase0;TNode:TCompop;for(base_t:iteratori=_vbase.begin();i!=end;+i)TNode*pNode=(*i);while
19、(pNode!=0)if(maxNode=0)|(op(pNode,maxNode)maxNode=pNode;pNode=pNode-pNext;v0=maxNode;elsev.resize(_node_count);intindex=0;if(_node_count0)TNode*end=&(_vbase_hash_power);for(TNode*i=&(_vbase0);i!=end;+i)TNode*pNode=(*i);while(pNode!=0)vindex=pNode;+index;pNode=pNode-pNext;std:partial_sort(v.begin(),v.begin()+sortCount,v.end(),TNo
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1