您的位置:首页 > 其它

关于建立倒排表搜索的一点心得

2015-05-03 14:36 387 查看
这几天刚刚用C写了一个关于倒排表搜索词条的程序,程序的效果还是可以,但是当词条数量增加后,算法的效率会大大降低。

这里将对算法进行简述,并总结得失。

一, 数据结构

将有两个文件作为索引的可持久化被保存。第一个我称为dictionary,第二个被称为data。

dictionary用来存储索引,其中索引是有序的。其中的每条索引数据包含代表该索引的一个HASH值,索引在data文件中第一次出现的位置FIRPOS和最后一次出现的位置LASTPOS

data用来存储所有出现过的词条,按照词条出现的顺序进行排列,每条数据记录该词条出现的位置和与该词条有同样HASH值的下一个词条位置。

二, 算法流程

初始化data和dic两个容器,用于在内存里存放data和dictionary两个文件,并建立对应的结构体——在面向对象语言中可以定义为类

读入要建立索引的数据(这里常常需要一个运行良好的分词器,推荐Python的Jieba分词,对中文分词的支持很好,其他语言可以通过运行一个python脚本来生成一个分词结果,然后再读入),加入data容器中

计算索引hash值,查找其在dic容器里的位置(可以假定dic容器里数据是有序的,因为我们在算法步骤中会维护其有序性),然后维护dictionary中的最后位置LASTPOS。(维护过程详见伪代码)最后回到第二步,重复,直到没有可以读入的数据为止,索引建立成功。

伪代码如下:

while (!eof)
{
tempData = ReadData;
Data = Divice(tempData);
loop:
hash(Data[i].value);
pos = find(Data[i].value) in dic.LASTPOS;
if pos == -1
new dic for Data[i].value;
else
/*以下就是维护的过程*/
dic[pos].next = i;
dic.LASTPOS = i;
sort(dic);
//结束维护
endloop;

}


三, 总结得失

这个算法总的来说在数据索引较小的时候,因为dictionary有序,find过程可以用二分查找来优化,然而这也引入了一个不好的地方——在索引数非常多的时候,每一步都排序的复杂度会非常大

即使有人推荐我用希尔排序,效果也并不是很好。所以我想到了对于dic容器,不用队列,而使用树结构,可以方便的做到查找和搜寻。可以尝试采用二叉搜索或者效率更高的红黑树(因为某些索引或许特别的长,这时候采用红黑树来降低树的高度很有必要)、

目前我还没有尝试过用树来优化。其实是因为我项目的问题,即使用二叉搜索树来做也很难让索引和一个int范围内的值产生一一对应。

这也将是我下一步将解决的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 倒排表