From 9ab4b0b15cd2fa1f192594c83ebe1e36bba9a008 Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Mon, 24 Jul 2023 12:46:48 +0800 Subject: [PATCH] Feature/array representation of tree swift (#649) * refactor: encode & decode Tree * style: build warning * feat: add Swift codes for array_representation_of_tree article --- codes/swift/Package.swift | 2 + .../preorder_traversal_i_compact.swift | 2 +- .../preorder_traversal_ii_compact.swift | 2 +- .../preorder_traversal_iii_compact.swift | 2 +- .../preorder_traversal_iii_template.swift | 2 +- .../chapter_tree/array_binary_tree.swift | 141 ++++++++++++++++++ codes/swift/chapter_tree/avl_tree.swift | 2 - .../chapter_tree/binary_search_tree.swift | 3 +- .../swift/chapter_tree/binary_tree_bfs.swift | 2 +- .../swift/chapter_tree/binary_tree_dfs.swift | 2 +- codes/swift/utils/PrintUtil.swift | 2 +- codes/swift/utils/TreeNode.swift | 70 ++++++--- 12 files changed, 200 insertions(+), 32 deletions(-) create mode 100644 codes/swift/chapter_tree/array_binary_tree.swift diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index 7ef714a93..f05608c71 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -35,6 +35,7 @@ let package = Package( .executable(name: "binary_tree", targets: ["binary_tree"]), .executable(name: "binary_tree_bfs", targets: ["binary_tree_bfs"]), .executable(name: "binary_tree_dfs", targets: ["binary_tree_dfs"]), + .executable(name: "array_binary_tree", targets: ["array_binary_tree"]), .executable(name: "binary_search_tree", targets: ["binary_search_tree"]), .executable(name: "avl_tree", targets: ["avl_tree"]), // chapter_heap @@ -120,6 +121,7 @@ let package = Package( .executableTarget(name: "binary_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_tree.swift"]), .executableTarget(name: "binary_tree_bfs", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_tree_bfs.swift"]), .executableTarget(name: "binary_tree_dfs", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_tree_dfs.swift"]), + .executableTarget(name: "array_binary_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["array_binary_tree.swift"]), .executableTarget(name: "binary_search_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_search_tree.swift"]), .executableTarget(name: "avl_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["avl_tree.swift"]), // chapter_heap diff --git a/codes/swift/chapter_backtracking/preorder_traversal_i_compact.swift b/codes/swift/chapter_backtracking/preorder_traversal_i_compact.swift index 1e656e70e..3174ca580 100644 --- a/codes/swift/chapter_backtracking/preorder_traversal_i_compact.swift +++ b/codes/swift/chapter_backtracking/preorder_traversal_i_compact.swift @@ -25,7 +25,7 @@ func preOrder(root: TreeNode?) { enum PreorderTraversalICompact { /* Driver Code */ static func main() { - let root = TreeNode.listToTree(list: [1, 7, 3, 4, 5, 6, 7]) + let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7]) print("\n初始化二叉树") PrintUtil.printTree(root: root) diff --git a/codes/swift/chapter_backtracking/preorder_traversal_ii_compact.swift b/codes/swift/chapter_backtracking/preorder_traversal_ii_compact.swift index 24205db2f..c12b292e6 100644 --- a/codes/swift/chapter_backtracking/preorder_traversal_ii_compact.swift +++ b/codes/swift/chapter_backtracking/preorder_traversal_ii_compact.swift @@ -30,7 +30,7 @@ func preOrder(root: TreeNode?) { enum PreorderTraversalIICompact { /* Driver Code */ static func main() { - let root = TreeNode.listToTree(list: [1, 7, 3, 4, 5, 6, 7]) + let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7]) print("\n初始化二叉树") PrintUtil.printTree(root: root) diff --git a/codes/swift/chapter_backtracking/preorder_traversal_iii_compact.swift b/codes/swift/chapter_backtracking/preorder_traversal_iii_compact.swift index edcbceefb..0f185bc0c 100644 --- a/codes/swift/chapter_backtracking/preorder_traversal_iii_compact.swift +++ b/codes/swift/chapter_backtracking/preorder_traversal_iii_compact.swift @@ -33,7 +33,7 @@ func preOrder(root: TreeNode?) { enum PreorderTraversalIIICompact { /* Driver Code */ static func main() { - let root = TreeNode.listToTree(list: [1, 7, 3, 4, 5, 6, 7]) + let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7]) print("\n初始化二叉树") PrintUtil.printTree(root: root) diff --git a/codes/swift/chapter_backtracking/preorder_traversal_iii_template.swift b/codes/swift/chapter_backtracking/preorder_traversal_iii_template.swift index 18940d993..22c59b9d4 100644 --- a/codes/swift/chapter_backtracking/preorder_traversal_iii_template.swift +++ b/codes/swift/chapter_backtracking/preorder_traversal_iii_template.swift @@ -56,7 +56,7 @@ func backtrack(state: inout [TreeNode], choices: [TreeNode], res: inout [[TreeNo enum PreorderTraversalIIITemplate { /* Driver Code */ static func main() { - let root = TreeNode.listToTree(list: [1, 7, 3, 4, 5, 6, 7]) + let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7]) print("\n初始化二叉树") PrintUtil.printTree(root: root) diff --git a/codes/swift/chapter_tree/array_binary_tree.swift b/codes/swift/chapter_tree/array_binary_tree.swift new file mode 100644 index 000000000..0986ee435 --- /dev/null +++ b/codes/swift/chapter_tree/array_binary_tree.swift @@ -0,0 +1,141 @@ +/** + * File: array_binary_tree.swift + * Created Time: 2023-07-23 + * Author: nuomi1 (nuomi1@qq.com) + */ + +import utils + +/* 数组表示下的二叉树类 */ +class ArrayBinaryTree { + private var tree: [Int?] + + /* 构造方法 */ + init(arr: [Int?]) { + tree = arr + } + + /* 节点数量 */ + func size() -> Int { + tree.count + } + + /* 获取索引为 i 节点的值 */ + func val(i: Int) -> Int? { + // 若索引越界,则返回 null ,代表空位 + if i < 0 || i >= size() { + return nil + } + return tree[i] + } + + /* 获取索引为 i 节点的左子节点的索引 */ + func left(i: Int) -> Int { + 2 * i + 1 + } + + /* 获取索引为 i 节点的右子节点的索引 */ + func right(i: Int) -> Int { + 2 * i + 2 + } + + /* 获取索引为 i 节点的父节点的索引 */ + func parent(i: Int) -> Int { + (i - 1) / 2 + } + + /* 层序遍历 */ + func levelOrder() -> [Int] { + var res: [Int] = [] + // 直接遍历数组 + for i in stride(from: 0, to: size(), by: 1) { + if let val = val(i: i) { + res.append(val) + } + } + return res + } + + /* 深度优先遍历 */ + private func dfs(i: Int, order: String, res: inout [Int]) { + // 若为空位,则返回 + guard let val = val(i: i) else { + return + } + // 前序遍历 + if order == "pre" { + res.append(val) + } + dfs(i: left(i: i), order: order, res: &res) + // 中序遍历 + if order == "in" { + res.append(val) + } + dfs(i: right(i: i), order: order, res: &res) + // 后序遍历 + if order == "post" { + res.append(val) + } + } + + /* 前序遍历 */ + func preOrder() -> [Int] { + var res: [Int] = [] + dfs(i: 0, order: "pre", res: &res) + return res + } + + /* 中序遍历 */ + func inOrder() -> [Int] { + var res: [Int] = [] + dfs(i: 0, order: "in", res: &res) + return res + } + + /* 后序遍历 */ + func postOrder() -> [Int] { + var res: [Int] = [] + dfs(i: 0, order: "post", res: &res) + return res + } +} + +@main +enum _ArrayBinaryTree { + /* Driver Code */ + static func main() { + // 初始化二叉树 + // 这里借助了一个从数组直接生成二叉树的函数 + let arr = [1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15] + + let root = TreeNode.listToTree(arr: arr) + print("\n初始化二叉树\n") + print("二叉树的数组表示:") + print(arr) + print("二叉树的链表表示:") + PrintUtil.printTree(root: root) + + // 数组表示下的二叉树类 + let abt = ArrayBinaryTree(arr: arr) + + // 访问节点 + let i = 1 + let l = abt.left(i: i) + let r = abt.right(i: i) + let p = abt.parent(i: i) + print("\n当前节点的索引为 \(i) ,值为 \(abt.val(i: i) as Any)") + print("其左子节点的索引为 \(l) ,值为 \(abt.val(i: l) as Any)") + print("其右子节点的索引为 \(r) ,值为 \(abt.val(i: r) as Any)") + print("其父节点的索引为 \(p) ,值为 \(abt.val(i: p) as Any)") + + // 遍历树 + var res = abt.levelOrder() + print("\n层序遍历为:\(res)") + res = abt.preOrder() + print("前序遍历为:\(res)") + res = abt.inOrder() + print("中序遍历为:\(res)") + res = abt.postOrder() + print("后序遍历为:\(res)") + } +} diff --git a/codes/swift/chapter_tree/avl_tree.swift b/codes/swift/chapter_tree/avl_tree.swift index 9d7df60e3..315d7f068 100644 --- a/codes/swift/chapter_tree/avl_tree.swift +++ b/codes/swift/chapter_tree/avl_tree.swift @@ -89,7 +89,6 @@ class AVLTree { } /* 插入节点 */ - @discardableResult func insert(val: Int) { root = insertHelper(node: root, val: val) } @@ -116,7 +115,6 @@ class AVLTree { } /* 删除节点 */ - @discardableResult func remove(val: Int) { root = removeHelper(node: root, val: val) } diff --git a/codes/swift/chapter_tree/binary_search_tree.swift b/codes/swift/chapter_tree/binary_search_tree.swift index 21894c4e1..f9e6d1ba8 100644 --- a/codes/swift/chapter_tree/binary_search_tree.swift +++ b/codes/swift/chapter_tree/binary_search_tree.swift @@ -90,7 +90,6 @@ class BinarySearchTree { } /* 删除节点 */ - @discardableResult func remove(num: Int) { // 若树为空,直接提前返回 if root == nil { @@ -160,7 +159,7 @@ enum _BinarySearchTree { PrintUtil.printTree(root: bst.getRoot()) /* 查找节点 */ - var node = bst.search(num: 7) + let node = bst.search(num: 7) print("\n查找到的节点对象为 \(node!),节点值 = \(node!.val)") /* 插入节点 */ diff --git a/codes/swift/chapter_tree/binary_tree_bfs.swift b/codes/swift/chapter_tree/binary_tree_bfs.swift index 0ddcb85f8..799aa29c2 100644 --- a/codes/swift/chapter_tree/binary_tree_bfs.swift +++ b/codes/swift/chapter_tree/binary_tree_bfs.swift @@ -31,7 +31,7 @@ enum BinaryTreeBFS { static func main() { /* 初始化二叉树 */ // 这里借助了一个从数组直接生成二叉树的函数 - let node = TreeNode.listToTree(list: [1, 2, 3, 4, 5, 6, 7])! + let node = TreeNode.listToTree(arr: [1, 2, 3, 4, 5, 6, 7])! print("\n初始化二叉树\n") PrintUtil.printTree(root: node) diff --git a/codes/swift/chapter_tree/binary_tree_dfs.swift b/codes/swift/chapter_tree/binary_tree_dfs.swift index 61695ef77..75dcadedf 100644 --- a/codes/swift/chapter_tree/binary_tree_dfs.swift +++ b/codes/swift/chapter_tree/binary_tree_dfs.swift @@ -48,7 +48,7 @@ enum BinaryTreeDFS { static func main() { /* 初始化二叉树 */ // 这里借助了一个从数组直接生成二叉树的函数 - let root = TreeNode.listToTree(list: [1, 2, 3, 4, 5, 6, 7])! + let root = TreeNode.listToTree(arr: [1, 2, 3, 4, 5, 6, 7])! print("\n初始化二叉树\n") PrintUtil.printTree(root: root) diff --git a/codes/swift/utils/PrintUtil.swift b/codes/swift/utils/PrintUtil.swift index 384c96199..d9a60b967 100644 --- a/codes/swift/utils/PrintUtil.swift +++ b/codes/swift/utils/PrintUtil.swift @@ -79,7 +79,7 @@ public enum PrintUtil { print("堆的数组表示:", terminator: "") print(queue) print("堆的树状表示:") - let root = TreeNode.listToTree(list: queue) + let root = TreeNode.listToTree(arr: queue) printTree(root: root) } diff --git a/codes/swift/utils/TreeNode.swift b/codes/swift/utils/TreeNode.swift index cdb7fef60..fe6e7c996 100644 --- a/codes/swift/utils/TreeNode.swift +++ b/codes/swift/utils/TreeNode.swift @@ -4,40 +4,68 @@ * Author: nuomi1 (nuomi1@qq.com) */ +/* 二叉树节点类 */ public class TreeNode { public var val: Int // 节点值 public var height: Int // 节点高度 public var left: TreeNode? // 左子节点引用 public var right: TreeNode? // 右子节点引用 + /* 构造方法 */ public init(x: Int) { val = x height = 0 } - public static func listToTree(list: [Int]) -> TreeNode? { - let size = list.count - if size == 0 { + // 序列化编码规则请参考: + // https://www.hello-algo.com/chapter_tree/array_representation_of_tree/ + // 二叉树的数组表示: + // [1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15] + // 二叉树的链表表示: + // /——— 15 + // /——— 7 + // /——— 3 + // | \——— 6 + // | \——— 12 + // ——— 1 + // \——— 2 + // | /——— 9 + // \——— 4 + // \——— 8 + + /* 将列表反序列化为二叉树:递归 */ + private static func listToTreeDFS(arr: [Int?], i: Int) -> TreeNode? { + if i < 0 || i >= arr.count || arr[i] == nil { return nil } - let root = TreeNode(x: list[0]) - var queue: [TreeNode] = [root] - var i = 0 - while !queue.isEmpty { - let node = queue.removeFirst() - i += 1 - if i >= size { - break - } - node.left = TreeNode(x: list[i]) - queue.append(node.left!) - i += 1 - if i >= size { - break - } - node.right = TreeNode(x: list[i]) - queue.append(node.right!) - } + let root = TreeNode(x: arr[i]!) + root.left = listToTreeDFS(arr: arr, i: 2 * i + 1) + root.right = listToTreeDFS(arr: arr, i: 2 * i + 2) return root } + + /* 将列表反序列化为二叉树 */ + public static func listToTree(arr: [Int?]) -> TreeNode? { + listToTreeDFS(arr: arr, i: 0) + } + + /* 将二叉树序列化为列表:递归 */ + private static func treeToListDFS(root: TreeNode?, i: Int, res: inout [Int?]) { + if root == nil { + return + } + while i >= res.count { + res.append(nil) + } + res[i] = root?.val + treeToListDFS(root: root?.left, i: 2 * i + 1, res: &res) + treeToListDFS(root: root?.right, i: 2 * i + 2, res: &res) + } + + /* 将二叉树序列化为列表 */ + public static func treeToList(root: TreeNode?) -> [Int?] { + var res: [Int?] = [] + treeToListDFS(root: root, i: 0, res: &res) + return res + } }