學習數據結構——二叉樹

雖然我在工作中從沒有用到過二叉樹這個結構,但是覺得還是挺重要的。emmm,就是這樣。

二叉樹:二叉樹的每個節點最多有兩個子節點,一般稱為左子節點和右子節點,二叉樹有左子樹和右子樹之分。

節點實現

public class TreeNode {
    public var val: Int
    public var left: TreeNode?
    public var right: TreeNode?
    public init(_ val: Int) {
        self.val = val
        self.left = nil
        self.right = nil
    }
}

二叉樹是由遞歸實現的,所以理論上所有的二叉樹問題都可以通過遞歸的方法來實現。
計算二叉樹最大深度

func maxDepth(_ root: TreeNode?) -> Int {
    guard let root = root else { return 0 }
    return max(maxDepth(root.left), maxDepth(root.right)) + 1
}

判斷一棵二叉樹是否二叉查找樹(二叉查找樹:所有左子樹節點的值都小于根節點的值,所有右子樹節點的值都大于根節點的值)

func isValidBST(_ root: TreeNode?) -> Bool{
    
    return helper(root, nil, nil)
}

func helper(_ node: TreeNode?, _ min: Int?, _ max:Int?) -> Bool{
    guard let node = node else {
        return true
    }
    if let min = min, node.val <= min {
        return false
    }
    if let max = max, node.val >= max{
        return false
    }
    return helper(node.left, min, node.val) && helper(node.right, node.val, max)
}

翻轉一顆二叉樹

func invertTree(_ root: TreeNode?) -> TreeNode? {
    if root == nil {
        return nil
    }
    let left = invertTree(root?.left)
    let right = invertTree(root?.right)
    
    root?.left = right
    root?.right = left
    return root
}

兩棵二叉樹求和

func MergeTree(_ t1: TreeNode?, _ t2: TreeNode?) -> TreeNode? {
    if (t1 == nil || t2 == nil) {return t1 == nil ? t2 : t1}
    let val = t1!.val + t2!.val
    let root = TreeNode(val)
    root.left = MergeTree(t1?.left, t2?.left)
    root.right = MergeTree(t1?.right, t2?.right)
    
    return root
}

遞歸遍歷二叉樹

func printTree(treeNode:TreeNode?) -> Int {
    if treeNode == nil {
        return 0
    }
    print(treeNode?.val as Any)
    printTree(treeNode: treeNode?.left)
    printTree(treeNode: treeNode?.right)
    return 1
}

非遞歸遍歷二叉樹(用棧實現前序遍歷)
思路:用棧來存放二叉樹的節點, 節點的左子樹為空時刪除該節點并將父節點的右子樹添加進棧

func preorderTraversal(root: TreeNode?) -> [Int] {
    var res = [Int]()
    var stack = [TreeNode]()
    var node = root
    
    while !stack.isEmpty || node != nil {
        if node != nil {
            res.append(node!.val)
            stack.append(node!)
            node = node!.left
        } else {
            node = stack.removeLast().right
        }
    }
    
    return res
}

用棧實現中序遍歷二叉樹

func cenOrderTraversal(root: TreeNode?) -> [Int] {
    var res = [Int]()
    var stack = [TreeNode]()
    var node = root
    
    while !stack.isEmpty || node != nil {
        if node != nil {
            stack.append(node!)
            node = node!.left
        } else {
            node = stack.removeLast()
            res.append(node!.val)
            node = node?.right
        }
    }
    
    return res
}

層級遍歷二叉樹

func levelOrder(root: TreeNode?) -> [[Int]] {
    var res = [[Int]]()
    var queue = [TreeNode]()
    
    if let root = root {
        queue.append(root)
    }
    
    while queue.count > 0 {
        let size = queue.count
        var level = [Int]()
        
        for _ in 0 ..< size {
            let node = queue.removeFirst()
            level.append(node.val)
            
            if let left = node.left {
                queue.append(left)
            }
            if let right = node.right {
                queue.append(right)
            }
        }
        res.append(level)
    }
    
    return res
    
}

鏈接如下:
故胤道長_二叉樹講解

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 遍歷方式 二叉樹的常見遍歷方式如下幾種: 前序遍歷: 訪問根節點,前序遍歷方式訪問左子樹,前序遍歷方式訪問右子樹;...
    zhipingChen閱讀 2,084評論 1 8
  • 本文主要作為自己的學習筆記,并不具備過多的指導意義。 目錄 基本概念 二叉樹的重點 二叉樹的遍歷 實現先序遍歷 實...
    kirito_song閱讀 1,382評論 0 5
  • 目錄 1、什么是樹 2、相關術語 3、二叉樹 3.1、二叉樹的類型 3.2、二叉樹的性質 3.3、二叉樹的結構 3...
    我哈啊哈啊哈閱讀 2,576評論 0 10
  • 一些概念 數據結構就是研究數據的邏輯結構和物理結構以及它們之間相互關系,并對這種結構定義相應的運算,而且確保經過這...
    Winterfell_Z閱讀 5,893評論 0 13
  • 你用心剪出了流水 剪出了風 剪出了 飛鳥的聲音 你用心剪出了遠山 剪出了流云 剪出了 一條條路引 最后 你把自...
    飛向遠方的魚閱讀 449評論 2 12