若是你谷歌“cool data structures”,你搜索到的第一个结果就会是这个内容。这是一个stackoverflow问题:“有哪些数据结构比较少人知道,可是颇有用?”,点赞最多的第一条答案就是字典树。我仔细研究了这些关于字典树答案,在其应用方面发现了一些有趣的事情(也发现我本身也是这种谷歌“cool data structures”的那种人),因此,我来到xcode playground,写下这些代码。xcode
字典树就是前缀树,是一种递归数据结构:每一个字典树都包含其余的子树,能够经过前缀来识别。数据结构
这是一种比较时髦的数据结构,并无被普遍的应用,可是确有一些很是实用的应用。它有相似集合的操做,包括插入和搜索操做时间复杂度在O(n),其中n是搜索序列的长度。集合是可hash的无序元素的惟一方式,可是,针对有序的hash元素序列,字典树或许更适合你。(有一件事须要告诉你,就是集合可以针对元素自身hash,因此,若是你想存储的序列是无序的,一个元素是集合的集合是更适合的。)less
A trie for keys “A”, “to”, “tea”, “ted”, “ten”, “i”, “in”, and “inn”.函数
在Swift里面,咱们可以使每个字典树包含一个字典,字典包含前缀和字典树。相似这样:spa
public struct Trie<Element : Hashable> {
private var children: [Element:Trie<Element>]
}
复制代码
咱们不会遇到结构体不能递归的状况,由于咱们不直接存储一个字典树在一个字典树里面——咱们存储的是一个字典,而且会关联到子字典树,在这个字典里面,前缀是这个字典的键值。因此,怎么补充接下来的内容呢(初始化)?咱们能够像列表生成器同样分解属性:code
extension Trie {
private init<G : GeneratorType where G.Element == Element>(var gen: G) {
if let head = gen.next() {
children = [head: Trie(gen: gen)]
} else {
children = [:]
}
}
public init<S : SequenceType where S.Generator.Element == Element>(_ seq: S) {
self.init(gen: seq.generator())
}
}
复制代码
这还不够,想要存储一个序列,咱们还要一个insert
函数,方法以下:cdn
extension Trie {
private mutating func insert<G : GeneratorType where G.Element = Element>(var gen: G) {
if let head = gen.next() {
children[head]?.insert(gen) ?? {children[head] == Trie(gen: gen)}()
}
}
public mutating func insert<S : SequenceType where S.Generator.Element == Element>(_ seq: S) {
insert(seq.generate())
}
}
复制代码