【北大天网搜索引擎TSE学习笔记】第5节——准备数据
上一节对搜索功能的入口程序TSESearch.cpp的main函数做了介绍,对搜索功能的实现的流程有了大概的了解,从这节开始讲对上节中提到的几个主要流程——准备数据、获取用户输入、中文分词、检索关键词、结果排序和显示搜索结果进行详细的分析。这一节分析准备数据的源代码。(这一节的内容非常简单,明白的朋友可以直接略过)
(1)加载字典
上一节的main函数中第12行定义了CDict对象iDict,CDict类为字典类。找到源代码./ChSeg/Dict.cpp,构造函数中调用了函数OpenDict,该函数很简单,就是打开了字典文件,然后从字典文件中逐行读出词加入到类成员mapDict中,也就是将字典内容从文件中加载到内存中,为后面的使用做好准备。
可以看到打开的文件是DICTFILENAME,找到该宏的定义为:conststringDICTFILENAME("words.dict"); 大家看到words.dict应该非常熟悉了,第2节中已经介绍过了,这就是字典文件。
另外,注意看一下字典是用什么数据结构存储的,看到./ChSeg/Dict.h中CDict类的声明,类中定义了:map<string,int>mapDict; ,说明字典在TSE中是用STL的map存储的,而STL中的map数据结构在底层是用红黑树实现的。为什么要提到字典存储的数据结构问题呢,因为字典的数据量是非常庞大的(我查看一下words.dict文件一共有108783行),而中文分词时需要频繁的在字典中查找指定的字符串是否存在,这将是影响搜索引擎效率的重要因素之一。如果字典不用优化的数据结构存储,每次都要遍历整个字典文件去查找的话,可以想象效率多么的低(O(n)的时间复杂度)!用红黑树存储的话,时间复杂度为O(log n),效率有很大提高。有的中文分词程序采用的是hash map来存储字典的,效率应该比红黑树更好。
(2)加载倒排表
上一节的main函数中第50行调用了GetInvLists函数,看到./Query.cpp中该函数的定义。代码也很简单,打开倒排索引文件,然后循环读出每一行存入mapBuckets中,也就是将倒排索引从文件中加载到内存中,为后面的使用做好准备。
可以看到打开的文件是INF_INFO_NAME,找到该宏的定义为:conststringINF_INFO_NAME("./Data/sun.iidx"); ,大家看到sun.iidx应该非常熟悉了,第2节中已经介绍过了,这就是倒排文件。
(3)加载网页索引
上一节的main函数中第53行调用了GetDocIdx函数,与上面相似,就是从网页索引文件(Doc.idx)加载到内存,为后面的使用做好准备。