funccontains(x:E) -> Bool { switchself { case .Leaf: returnfalse caselet .Node(_, y, _) where x == y: returntrue caselet .Node(left, y, _) where x < y: returnleft.contains(x: x) caselet .Node(_, y, right) where x > y: returnright.contains(x: x) default: fatalError() } }
如果树是空的,则 x 不在树中,返回 false。
如果树不为空,且储存在根节点的值与 x 相等,返回 true。
如果树不为空,且储存在根节点的值大于 x,那么如果 x 在树中的话,它一定是在左子树中,所以,我们在左子树中递归搜索 x。
类似地,如果根节点的值小于 x,我们就在右子树中继续搜索。
插入一个元素
1 2 3 4 5 6 7 8 9 10
mutatingfuncinsert(x:E) { switchself { case .Leaf: self = BinarySearchTree.init(value: x) case .Node(varleft, let y, varright): if x < y {left.insert(x: x)} if x > y {right.insert(x: x)} self = .Node(left, y, right) } }
如果键组不为空,且键组的 head 已经存在于当前节点的 children 字典中,我们只需要递归地调用该函数,将键组的 tail 插入到对应的子字典树中。
如果键组不为空,且第一个键 head 并不是该字典树中 children 字典的某条记录,就创建一棵新的字典树来储存键组中剩下的键。然后,以 head 键和 tail 数组生成对应新的字典树,储存在当前节点中,完成插入操作。
然后我们就可以定义一个方法来将一个关联数组组合成字典树
1 2 3 4 5 6
funcbuildStringTrie(words:[String]) -> Trie<Character> { let emptyTrie = Trie<Character>.init() return words.reduce(emptyTrie, { (result, word) -> Trie<Character> in result.insert(key: Array.init(word)) }) }
打印方法,打印出字典树中包含的所有关联元素
1 2 3 4 5 6 7
var elements: [[Element]] { var result: [[Element]] = isElement ? [[]] : [] for (key, value) in children { result += value.elements.map { [key] + $0 } } return result }
让我们用一个简单的例子来测试,首先用 [“cart”, “car”] 数组来生成一个字典树,然后在 elements 过程中进行打印
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
{ let contents = ["cart", "car"] let trie = buildStringTrie(words:contents) print(trie.elements) }
{ var elements: [[Element]] { var result: [[Element]] = isElement ? [[]] : [] for (key, value) in children { result += value.elements.map { [key] + $0 } } print(result) return result } }