树可以用数组存储吗_读不懂的双数组存储的trie树

973961975c759a3011ffffdf635c9c61.png

看了两天,这个双数组是怎么存储trie树的也没看明白。你去搜各种文章吗,一个人一个说法,就是没一个写明白的。试图看了一下原始作者的代码(又是日本人),

komiya-atsushi/darts-java​github.com
774237960b4af8ed39394b9439be9636.png

实在没看下去,全是n,p,i的字母变量,所以决定放弃,我可不较这个劲,而且也没啥用途。有谁不服的,可以来给我讲讲,毕恭毕敬地听。你也可以看看HanLP作者写的教程,也是不怎么样。

双数组Trie树(DoubleArrayTrie)Java实现-码农场​www.hankcs.com

1. trie树

先来说trie树,trie树的树结构很好理解,大部分文章也都能说明白,这里只简要说明。trie树是按照排序后的词典存储的。这里引用HanLP的图了。

03b307ddd3423622c5a010c17cb267f8.png

显然,树的每i行对应于词典中词语的第i个字,因此在存储前需要对词典中的单词进行排序。具有相同前缀的词语会在一棵子树上。

2. 双数组trie树

这里对于双数组trie树的原理不进行阐述,原因前边已经说过,它的想法其实很简单,就是用两个数组来存储一棵trie树,这种存储方法不仅节省内存空间而且检索词语的速度也非常快。放一个HanLP中的示例在下边,这个示例我直接用的darts-java。

package darts;

import darts.DoubleArrayTrie;

import java.io.*;
import java.util.*;

public class DemoDoubleArrayTrie {
	public static void main(String[] args) throws IOException {
		// 读入词典
		BufferedReader reader = new BufferedReader(new FileReader("./data/small.dic"));
		String line;
		List<String> words = new ArrayList<String>();
		Set<Character> charset = new HashSet<Character>();
		while ((line = reader.readLine()) != null) {
			words.add(line);
			// 制作一份码表debug
			for (char c : line.toCharArray()) {
				charset.add(c);
			}
		}
		reader.close();
		
		// 输出汉字以及对应的汉字编码
		System.out.println("字典词条:" + words.size());

		{
			String infoCharsetValue = "";
			String infoCharsetCode = "";
			for (Character c : charset) {
				// 读出1个汉字
				infoCharsetValue += c.charValue() + "    ";
				// 读出该汉字的编码
				infoCharsetCode += (int) c.charValue() + " ";
			}
			infoCharsetValue += 'n';
			infoCharsetCode += 'n';
			System.out.print(infoCharsetValue);
			System.out.print(infoCharsetCode);
		}
		
		// 构建双数组trie树
		DoubleArrayTrie dat = new DoubleArrayTrie();
		System.out.println("是否错误: " + dat.build(words));
		System.out.println(dat.toString());
		
		// 公共前缀匹配
		List<Integer> integerList = dat.commonPrefixSearch("一举成名天下知");
		for (int index : integerList) {
			System.out.println(words.get(index));
		}
	}
}

输出结果

字典词条:6
一    成    知    胶    万    动    天    下    名    能    举    
19968 25104 30693 33014 19975 21160 22825 19979 21517 33021 20030 
是否错误: 0
darts.DoubleArrayTrie@7852e922
一举
一举成名
一举成名天下知

如果有哪个小伙伴想挑战读这段代码,彻底弄明白到底是怎么用两个数组来存储trie树,那就直接下载darts-java来看吧,我估计全国也没几个认真看过这个代码的,也或者看了也没看懂。招聘面试的也没人敢提,直到为啥不,因为他自己都讲不明白。这就叫日本人都嚼的没味的东西,中国人依然搞不明白。

准备撸串去喽,6点准时开始。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值