mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-25 12:56:29 +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", targets: ["binary_tree"]),
|
||||||
.executable(name: "binary_tree_bfs", targets: ["binary_tree_bfs"]),
|
.executable(name: "binary_tree_bfs", targets: ["binary_tree_bfs"]),
|
||||||
.executable(name: "binary_tree_dfs", targets: ["binary_tree_dfs"]),
|
.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: "binary_search_tree", targets: ["binary_search_tree"]),
|
||||||
.executable(name: "avl_tree", targets: ["avl_tree"]),
|
.executable(name: "avl_tree", targets: ["avl_tree"]),
|
||||||
// chapter_heap
|
// 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", 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_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: "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: "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"]),
|
.executableTarget(name: "avl_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["avl_tree.swift"]),
|
||||||
// chapter_heap
|
// chapter_heap
|
||||||
|
|
|
@ -25,7 +25,7 @@ func preOrder(root: TreeNode?) {
|
||||||
enum PreorderTraversalICompact {
|
enum PreorderTraversalICompact {
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
static func main() {
|
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初始化二叉树")
|
print("\n初始化二叉树")
|
||||||
PrintUtil.printTree(root: root)
|
PrintUtil.printTree(root: root)
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ func preOrder(root: TreeNode?) {
|
||||||
enum PreorderTraversalIICompact {
|
enum PreorderTraversalIICompact {
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
static func main() {
|
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初始化二叉树")
|
print("\n初始化二叉树")
|
||||||
PrintUtil.printTree(root: root)
|
PrintUtil.printTree(root: root)
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ func preOrder(root: TreeNode?) {
|
||||||
enum PreorderTraversalIIICompact {
|
enum PreorderTraversalIIICompact {
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
static func main() {
|
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初始化二叉树")
|
print("\n初始化二叉树")
|
||||||
PrintUtil.printTree(root: root)
|
PrintUtil.printTree(root: root)
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ func backtrack(state: inout [TreeNode], choices: [TreeNode], res: inout [[TreeNo
|
||||||
enum PreorderTraversalIIITemplate {
|
enum PreorderTraversalIIITemplate {
|
||||||
/* Driver Code */
|
/* Driver Code */
|
||||||
static func main() {
|
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初始化二叉树")
|
print("\n初始化二叉树")
|
||||||
PrintUtil.printTree(root: root)
|
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) {
|
func insert(val: Int) {
|
||||||
root = insertHelper(node: root, val: val)
|
root = insertHelper(node: root, val: val)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +115,6 @@ class AVLTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 删除节点 */
|
/* 删除节点 */
|
||||||
@discardableResult
|
|
||||||
func remove(val: Int) {
|
func remove(val: Int) {
|
||||||
root = removeHelper(node: root, val: val)
|
root = removeHelper(node: root, val: val)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,6 @@ class BinarySearchTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 删除节点 */
|
/* 删除节点 */
|
||||||
@discardableResult
|
|
||||||
func remove(num: Int) {
|
func remove(num: Int) {
|
||||||
// 若树为空,直接提前返回
|
// 若树为空,直接提前返回
|
||||||
if root == nil {
|
if root == nil {
|
||||||
|
@ -160,7 +159,7 @@ enum _BinarySearchTree {
|
||||||
PrintUtil.printTree(root: bst.getRoot())
|
PrintUtil.printTree(root: bst.getRoot())
|
||||||
|
|
||||||
/* 查找节点 */
|
/* 查找节点 */
|
||||||
var node = bst.search(num: 7)
|
let node = bst.search(num: 7)
|
||||||
print("\n查找到的节点对象为 \(node!),节点值 = \(node!.val)")
|
print("\n查找到的节点对象为 \(node!),节点值 = \(node!.val)")
|
||||||
|
|
||||||
/* 插入节点 */
|
/* 插入节点 */
|
||||||
|
|
|
@ -31,7 +31,7 @@ enum BinaryTreeBFS {
|
||||||
static func main() {
|
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")
|
print("\n初始化二叉树\n")
|
||||||
PrintUtil.printTree(root: node)
|
PrintUtil.printTree(root: node)
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ enum BinaryTreeDFS {
|
||||||
static func main() {
|
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")
|
print("\n初始化二叉树\n")
|
||||||
PrintUtil.printTree(root: root)
|
PrintUtil.printTree(root: root)
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public enum PrintUtil {
|
||||||
print("堆的数组表示:", terminator: "")
|
print("堆的数组表示:", terminator: "")
|
||||||
print(queue)
|
print(queue)
|
||||||
print("堆的树状表示:")
|
print("堆的树状表示:")
|
||||||
let root = TreeNode.listToTree(list: queue)
|
let root = TreeNode.listToTree(arr: queue)
|
||||||
printTree(root: root)
|
printTree(root: root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,40 +4,68 @@
|
||||||
* Author: nuomi1 (nuomi1@qq.com)
|
* Author: nuomi1 (nuomi1@qq.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* 二叉树节点类 */
|
||||||
public class TreeNode {
|
public class TreeNode {
|
||||||
public var val: Int // 节点值
|
public var val: Int // 节点值
|
||||||
public var height: Int // 节点高度
|
public var height: Int // 节点高度
|
||||||
public var left: TreeNode? // 左子节点引用
|
public var left: TreeNode? // 左子节点引用
|
||||||
public var right: TreeNode? // 右子节点引用
|
public var right: TreeNode? // 右子节点引用
|
||||||
|
|
||||||
|
/* 构造方法 */
|
||||||
public init(x: Int) {
|
public init(x: Int) {
|
||||||
val = x
|
val = x
|
||||||
height = 0
|
height = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func listToTree(list: [Int]) -> TreeNode? {
|
// 序列化编码规则请参考:
|
||||||
let size = list.count
|
// https://www.hello-algo.com/chapter_tree/array_representation_of_tree/
|
||||||
if size == 0 {
|
// 二叉树的数组表示:
|
||||||
|
// [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
|
return nil
|
||||||
}
|
}
|
||||||
let root = TreeNode(x: list[0])
|
let root = TreeNode(x: arr[i]!)
|
||||||
var queue: [TreeNode] = [root]
|
root.left = listToTreeDFS(arr: arr, i: 2 * i + 1)
|
||||||
var i = 0
|
root.right = listToTreeDFS(arr: arr, i: 2 * i + 2)
|
||||||
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!)
|
|
||||||
}
|
|
||||||
return root
|
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