您的位置:首页 > 其它

关于拼音的datrie树的修改

2016-05-05 09:29 239 查看
DATrie树的逻辑模型

原有的建树规则

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

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

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

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

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

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

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

原有的项目的性能瓶颈

最主要影响性能的地方,在于,当层次遍历的过程中, 到达该层的路径,与该路径后续的边, 都建立了stl的map容器。并且,又重新建立了一个同样容量的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 列, 如果连续的两行,他们的前 j 个字符相等, 那么他们将具有相同的前缀,而他们的 第 j+1 个字符,将是该路径的向后的边的向量。如果该 第 j+1 个字符,也相同,那么就说明他们具有相同的向后的边,依然是同一条路径, 不能分开存储。

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

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

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

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

取出该层,对每个不同的路径,按照这些不同的路径的 向后的边 的个数, 由大到小排序, 前一半依次占用 存储数组的位置, 后一半从数组开始,查找能符合存储个数的连续空间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: