关于拼音的datrie树的修改

来源:互联网 发布:免费手机挂机赚钱软件 编辑:程序博客网 时间:2024/05/01 00:19

 

DATrie树的逻辑模型

 

 

原有的建树规则

 

该树的建立,是以字典中,相应的拼音为材料进行创建,对树的遍历,其实本质上是搜寻拼音是否存在,以层为基础,最长的字符串的长度,是该树的深度。 按层扫描所有的拼音。 

在字典文件中,表现为,按照最长字符串的长度,进行for循环,每次循环,每个拼音的前i个,表示到了i层。

i个字符,到了第i层的路径。 获得前i个字符相同的拼音,这含义是,他们归属该i层的同一个路径,将后一个字符记录下来,这些前i个字符相同的拼音,第 i+1 个字符,是该路径,向下子节点的边。

这样,在层次遍历的过程中,获得相同层次,同一个路径的向后的边的值和数目。

按路径向后的边的数目,从大到小排序后, 前一半的路径, 直接从存储数组顺序可用的位置获取数值,给该路径的本层节点的base[i]赋值,然后按照 base + 边向量 的值,顺序占用存储空间的位置。

前一半的路径i,不断的占用存储空间, 该过程,将会导致空位置,路径向后的边,的向量值,有可能是不连续的,那么在存储数组中占用的位置,也将是不连续。 这一点,将导致空间浪费。

后一半的路径, 从存储数组的开始,逐次寻找满足 该路径的向后的边的数据的 连续空间, 该过程会填充前一半路径占用存储数组位置时候,没有用到的空间。

 

原有的项目的性能瓶颈

 

最主要影响性能的地方,在于,当层次遍历的过程中, 到达该层的路径,与该路径后续的边, 都建立了stlmap容器。并且,又重新建立了一个同样容量的vector, 对该map进行排序。 每个路径都是一个map映射,造成了大量的内存占用,并且由于在层次遍历过程中,动态开辟这些stl容器,导致耗费了大量的cpu时间,致使运行时间过长。

 

解决方法,在不破坏该数学模型,以及整体的思路的情况下,修改在层次遍历的过程中, 相应的对 路径 =》 向后的边  map映射的结构。 针对字典文件的特性,建立一个矩阵,矩阵的行的个数,是pinyin的个数, 矩阵的列的个数,是最大字符串的长度, 列代表树的深度, 行代表该层所有的节点。

 

 

字典文件中,对pinyin的存储

a

a

b

d

 

 

 

a

b

b

e

 

 

 

b

a

s

y

 

 

 

b

a

z

 

 

 

 

 i 行 *  j

 

 

优化策略利用了拼音文件中,拼音字符存储顺序的特性。

拼音文件中,拼音的顺序,是按照列, ascii 码 由低到高 排列, 并且,相同列树的两行,总是满足, line[j] <= next_line[j] ascii码。

 

那么,在第 列, 如果连续的两行,他们的前 个字符相等, 那么他们将具有相同的前缀,而他们的 第  j+1 个字符,将是该路径的向后的边的向量。如果该 第 j+1 个字符,也相同,那么就说明他们具有相同的向后的边,依然是同一条路径, 不能分开存储。

 

优化的原则,主要在于,修改原有的结构中,在第 层,该层相同的路径,与后面的边,之间的 map映射结构

按照数组来存储 拼音字符, 那前 个字符相同的连续的行,并且必须满足 第 j+1 个字符不同,那么他们符合原有的项目中,相应的 key => value 映射关系。

原有的项目,利用了set容器,用来规避相同的第 j+1 个字符相同, 会导致该路径向后的边的统计失效的情况。

 

随后的策略与原有项目保持一致。 

取出该层,对每个不同的路径,按照这些不同的路径的 向后的边 的个数, 由大到小排序, 前一半依次占用 存储数组的位置, 后一半从数组开始,查找能符合存储个数的连续空间。

 

 

 

 

0 0
原创粉丝点击