若是你谷歌「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())
}
}
複製代碼