字典树(Trie)-Swift实现

若是你谷歌“cool data structures”,你搜索到的第一个结果就会是这个内容。这是一个stackoverflow问题:“有哪些数据结构比较少人知道,可是颇有用?”,点赞最多的第一条答案就是字典树。我仔细研究了这些关于字典树答案,在其应用方面发现了一些有趣的事情(也发现我本身也是这种谷歌“cool data structures”的那种人),因此,我来到xcode playground,写下这些代码。xcode

字典树就是前缀树,是一种递归数据结构:每一个字典树都包含其余的子树,能够经过前缀来识别。数据结构

这是一种比较时髦的数据结构,并无被普遍的应用,可是确有一些很是实用的应用。它有相似集合的操做,包括插入和搜索操做时间复杂度在O(n),其中n是搜索序列的长度。集合是可hash的无序元素的惟一方式,可是,针对有序的hash元素序列,字典树或许更适合你。(有一件事须要告诉你,就是集合可以针对元素自身hash,因此,若是你想存储的序列是无序的,一个元素是集合的集合是更适合的。)less

trie

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())
    }
}
复制代码
相关文章
相关标签/搜索