double array trie

* Double Array Trie是TRIE树的一种变形,它是在保证TRIE树检索速度的前提下,提高空间利用率而提出的一种数据结构,本质上是一个确定有限自动机(deterministic finite automaton,简称DFA)。

* 所谓的DFA就是一个能实现状态转移的自动机。对于一个给定的属于该自动机的状态和一个属于该自动机字母表Σ的字符,它都能根据事先给定的转移函数转移到下一个状态。

* 对于Double Array Trie(以下简称DAT),每个节点代表自动机的一个状态,根据变量的不同,进行状态转移,当到达结束状态或者无法转移的时候,完成查询。

 

    实现: 在tire树种,每个节点的子节点是稀疏的,比如英文字典,每个节点有26个子节点,实际使用的很少,比如下图 (1),是不是可以把孩子节点挤一挤放到一起呢?入图(2)

 

double array trie_第1张图片

 这个时候,就有问题了,发现不知道哪些是自己的儿子了?怎么办呢,那就叫儿子记下自己的老子是谁,所以如图(3),使用了一个check数组来保存自己的父节点。 最后我们把父子节点都组合到一起,如图(4),使用两个数组就可以存放了,第一个数组存在了儿子的基地址,第二个存放了父节点的地址。

 

         在查找的时候:

 

base[s]  +  c  ==  t
check[base[s] 
+  c]  ==  s

 

第一个表示通过父节点的基地址+ 节点的偏移量,找到孩子节点。 第一个是验证找到的孩子节点的确是该节点的孩子。

 

 

        创建:

  • 当n条词语准备构建双数组时,先以添加一条词语cat为例,双数组中base[1024]数组根节点为0(默认值,当然根据“个人爱好”可以随意指定),下标为0,为词语cat的首字符"c“(2)找一个合适的位置,比如位置0,即:
  • base[0] = 0;
  • 此处那么在base[0]的位置下,加上字符"c"的值得到下一个状态(t)的位置(2),然后在一个合适的位置(空闲的位置)4,使得
  • base[2]+’a'=4;
  • 那么状态(t),即base[2]的值可以通过上述公式得到4 
  • 值得注意是,在状态(f),目前即字符"t",结束时,其value值可以做如下处理,如果状态(f)结束,没有子节点,则
  • base(f)=-1 * f;
  • 如果状态(t)结束,仍然有多个子节点,那么其base数组标记为
  • base(f)=-1 * base(f);
  • 当输入第二条词语camera时,仍然按照上述方式进行,当进行到字符a时,字符a位置的下标为4,检查check[base[4]+’m']是否为空位。
    • 如果为空位,则base[4]的值仍然可以为不变;
    • 否则需要重新寻找两个空位位置Ψ(base[4]+’m'),λ(base[4]+’t'),使得 base[base[4]+’m']=-1(-1标记为空位状态,"m"为camera的第三个字符)和 base[base[4]+’t']=-1("t"为cat的第三个字符),即第二级节点a后面的两个新节点能有位置存放新的偏移量,并使得 check[base[4]+’m']=4和check[base[4]+’t']=4即可,那么base[4]的值需重新指向到新 的位置(Ψ+λ-’m'-’t')/2。
  • 接着继续重新构建下面新两个节点的DAT结构,且第一个节点的结构构造完成后,需要清除原来的构建。

 

所以整个过程中,都是在寻找每个节点的base值。

 

你可能感兴趣的:(数据结构,c)