在这篇博客里,会教给大家如何实现一个Swift tree的数据结构。这是一个比较普遍而且有用的数据结构,也是你学习最好的一个开始。
翻译自:https://www.raywenderlich.com/138190/swift-algorithm-club-swift-tree-data-structure
Tree数据结构:
最简单的方式来理解Tree数据结构是通过一个图片:
上面的图显示出了Tree有五个Level, root的level是0,接着,每深入一层,level便增加1.
Tree可以帮助你解决很多的重要问题, 包括:表示对象之间的层次关系,让搜索变的更有效快捷, 提供一个排序的列表数据, 为前缀匹配文本字段。
接下来,我们学习一些术语用来理解Tree.
Root: Root就是Tree指向Level 0的node,你可以把它认为是你Tree数据结构的进入点。
Node: 一个Node是一个数据块,在Tree结构中。 也就是这个节点中包含的数据是依靠这个Tree的类型。Root也是一个Node.
Leaf : 一些情况下,指向的是一个末端节点node,一个leaf是一个简单的node节点没有children, 举个例子,如果node对象有left child,然后right child是nil空,那么你可以认为这个node就是一个leaf.
Tree在Swift里的实现:
在这一节里,你会实现一个一般用途的Tree. 这是一个没有任何限制的Tree, (就像每个node会有多少的child, 多少节点nodes)
记住一点:每一个tree都是由nodes组成的。 所以开始之前,我们先建立一个基本的node类。创建一个新swift playground, 然后添加下面的空类:
class Node { }
Value: 你将要用到这个tree来管理字符串数据。 更新你的代码:
class Node { var value: String init(value: String) { self.value = value } }
你定义了一个属性叫做value, 类型是string. 你还声明了一个初始值,是一个需要被初始化的属性。
Children: 对于children, 每一个node需要一些children.
更新你的类定义:
class Node { var value: String var children: [Node] = [] // add the children property init(value: String) { self.value = value } }你简单的声明了children是一个数组的node, 每一个child代表了一个node, 也就是level 1低一级的当前节点。
Parent: 有些时候,很快捷便利的是每一个node都有一个link指向它的parent node. Children是node下一级的节点, 而parent则是上一级的节点。 一个node只有一个parent, 但是可以有很多的children.
更新你的node类代码:
class Node { var value: String var children: [Node] = [] weak var parent: Node? // add the parent property init(value: String) { self.value = value } } |
Insertion: 为了在tree中控制insertion, 你需要声明一个add(child:)方法,更新你的运行代码:
class Node { var value: String var children: [Node] = [] weak var parent: Node? init(value: String) { self.value = value } func add(child: Node) { children.append(child) child.parent = self } }
这个是最好的理解方式,来理解addChild()是怎样工作的,在你的类之外,写下面的代码:
let beverages = Node(value: "beverages") let hotBeverages = Node(value: "hot") let coldBeverages = Node(value: "cold") beverages.add(child: hotBeverages) beverages.add(child: coldBeverages) |
多级结构是很常见的在数据结构中,所以当你定义3种不同的nodes,然后组织他们进入一个合理的层级。那么对应的结构应该如下图所示:
Printing Trees: 打印输出trees
验证一个大型的tree结构是比较困难的,如果没有人和的控制台日志记录。在你定义了你的tree structure之后,登录控制台打印tree.
print(beverages) // <- try to print it!
你可以打开控制台按下组合键:Command+Shift+Y, 那么你可以看到你的类的名称打印到了控制台。
你需要让Node符合CustomStringConvertible的协议。 那么添加下面的代码到你的Node类中:
// 1 extension Node: CustomStringConvertible { // 2 var description: String { // 3 var text = "\(value)" // 4 if !children.isEmpty { text += " {" + children.map { $0.description }.joinWithSeparator(", ") + "} " } return text } } |
现在,当你调用print 你的node类,你会得到下面的显示:
"beverages {hot {tea {black, green, chai} , coffee, cocoa} , cold {soda {ginger ale, bitter lemon} , milk} } \n"