题目:二叉树遍历
class TreeNode {
var val: Int
var left: TreeNode?
var right: TreeNode?
}
前序遍历
func preorderTraversal(_ root: TreeNode?) -> [Int] {
var result: [Int] = []
guard let root = root else { return result } // 如果根节点为空,直接返回空数组
// 递归实现前序遍历
preorderTraversalHelper(root, &result)
return result
}
func preorderTraversalHelper(_ node: TreeNode, _ result: inout [Int]) {
if let node = node {
// 访问根节点
result.append(node.val)
// 遍历左子树
preorderTraversalHelper(node.left, &result)
// 遍历右子树
preorderTraversalHelper(node.right, &result)
}
}
//中序遍历
func inorderTraversal(_ root: TreeNode?) -> [Int] {
var result: [Int] = []
guard let root = root else { return result } // 如果根节点为空,直接返回空数组
// 递归实现中序遍历
inorderTraversalHelper(root, &result)
return result
}
func inorderTraversalHelper(_ node: TreeNode, _ result: inout [Int]) {
if let node = node {
// 遍历左子树
inorderTraversalHelper(node.left, &result)
// 访问根节点
result.append(node.val)
// 遍历右子树
inorderTraversalHelper(node.right, &result)
}
}
后续遍历
func postorderTraversal(_ root: TreeNode?) -> [Int] {
var result: [Int] = []
guard let root = root else { return result } // 如果根节点为空,直接返回空数组
// 递归实现后序遍历
postorderTraversalHelper(root, &result)
return result
}
func postorderTraversalHelper(_ node: TreeNode, _ result: inout [Int]) {
if let node = node {
// 遍历左子树
postorderTraversalHelper(node.left, &result)
// 遍历右子树
postorderTraversalHelper(node.right, &result)
// 访问根节点
result.append(node.val)
}
}
inout是 Swift 中的关键字,可以放置于参数类型前,冒号之后。使用 inout之后,函数体内部可以直接更改参数值,而且改变会保留。
func swap(resSct: inout ResolutionStruct) {
withUnsafePointer(to: &resSct) { print("During calling: ($0)") }
let temp = resSct.height
resSct.height = resSct.width
resSct.width = temp
}
var iPhone6ResoStruct = ResolutionStruct(height: 1334, width: 750)
print(iPhone6ResoStruct)
withUnsafePointer(to: &iPhone6ResoStruct) { print("Before calling: (0)") }
小结:值类型变量作为参数传入函数,外界和函数参数的内存地址一致,函数内对参数的更改得到了保留。
需要注意的是:
1.使用 inout 关键字的函数,在调用时需要在该参数前加上 & 符号
2.inout 参数在传入时必须为变量,不能为常量或字面量(literal)
3.inout 参数不能有默认值,不能为可变参数
4.inout 参数不等同于函数返回值,是一种使参数的作用域超出函数体的方式
5.多个inout 参数不能同时传入同一个变量,因为拷入拷出的顺序不定,那么最终值也不能确定
struct Point {
var x = 0.0
var y = 0.0
}
struct Rectangle {
var width = 0.0
var height = 0.0
var origin = Point()
var center: Point {
get {
print("center GETTER call")
return Point(x: origin.x + width / 2,
y: origin.y + height / 2)
}
set {
print("center SETTER call")
origin.x = newValue.x - width / 2
origin.y = newValue.y - height / 2
}
}
func reset(center: inout Point) {
center.x = 0.0
center.y = 0.0
}
}
var rect = Rectangle(width: 100, height: 100, origin: Point(x: -100, y: -100))
print(rect.center)
rect.reset(center: &rect.center)
print(rect.center)
// center GETTER call
// Point(x: -50.0, y: -50.0)
// center GETTER call
// center SETTER call
// center GETTER call
// Point(x: 0.0, y: 0.0)
inout参数的传递过程:
当函数被调用时,参数值被拷贝
在函数体内,被拷贝的参数修改
函数返回时,被拷贝的参数值被赋值给原有的变量