mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-25 00:06:28 +08:00
Feature/array representation of tree swift (#649)
* refactor: encode & decode Tree * style: build warning * feat: add Swift codes for array_representation_of_tree article
This commit is contained in:
parent
c1adeb2399
commit
9ab4b0b15c
12 changed files with 200 additions and 32 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
141
codes/swift/chapter_tree/array_binary_tree.swift
Normal file
141
codes/swift/chapter_tree/array_binary_tree.swift
Normal file
|
@ -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)")
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)")
|
||||
|
||||
/* 插入节点 */
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue