二叉樹(shù) for iOS (Swift篇)

學(xué)習(xí)了二叉樹(shù)的概念二叉樹(shù)算法習(xí)題后, 結(jié)合學(xué)習(xí)的知識(shí)通過(guò)代碼實(shí)現(xiàn)一些功能。

二叉樹(shù)說(shuō)白了是考驗(yàn)程序員的遞歸思維,通過(guò)自己調(diào)用自己來(lái)實(shí)現(xiàn)功能,廢話不多說(shuō)上代碼。

創(chuàng)建二叉樹(shù)類(lèi)

創(chuàng)建BinaryTreeNode類(lèi),并分別創(chuàng)建value、leftNode、rightNode屬性,導(dǎo)入數(shù)組創(chuàng)建二叉樹(shù)

class BinaryTreeNode: NSObject {
   // 值
   var value:Int = 0
   // 左節(jié)點(diǎn)
   var leftNode:BinaryTreeNode?
   // 右節(jié)點(diǎn)
   var rightNode:BinaryTreeNode?
   
   /// 創(chuàng)建二叉樹(shù)排序樹(shù)節(jié)點(diǎn)
   /// 左節(jié)點(diǎn)值全部小于根節(jié)點(diǎn),右節(jié)點(diǎn)值全部大于根節(jié)點(diǎn)
   ///
   /// - Parameter values: 數(shù)組
   /// - Returns: 二叉樹(shù)根節(jié)點(diǎn)
   class func creatTree(values: [Int]) -> BinaryTreeNode {
        var root:BinaryTreeNode?
        for i in 0..<values.count {
            let value = values[i]
            root = BinaryTreeNode.addTreeNode(treeNode: root, value: value)
        }
        return root!
    }
    
   /// 向二叉排序樹(shù)添加一個(gè)節(jié)點(diǎn)
   ///
   /// - Parameters:
   ///   - treeNode: 根節(jié)點(diǎn)
   ///   - value: 值
   /// - Returns: 根節(jié)點(diǎn)
   private class func addTreeNode(treeNode: BinaryTreeNode?, value:Int) -> BinaryTreeNode? {
        var treeNode = treeNode
        if treeNode == nil {
            treeNode = BinaryTreeNode()
            treeNode?.value = value
            print("node: \(value)")
        } else if value <= treeNode!.value {
            print("to left")
            // 值小于根節(jié)點(diǎn)
            treeNode?.leftNode = BinaryTreeNode.addTreeNode(treeNode: treeNode?.leftNode, value: value)
        } else {
            print("to right")
            // 值大于根節(jié)點(diǎn)
            treeNode?.rightNode = BinaryTreeNode.addTreeNode(treeNode: treeNode?.rightNode, value: value)
        }
        return treeNode
   }
}      

在合適的地方調(diào)用方法創(chuàng)建二叉樹(shù),筆者為了清晰的看到樹(shù)的結(jié)構(gòu),通過(guò)笨方法打印了每層子節(jié)點(diǎn):

let array = [1, 2, 10, 8, 3, 4, 5, 6, 7, 9]
let tree = BinaryTreeNode.creatTree(values: array)

print("<===============> 1層")
print(tree.value)

print("<===============> 2層")
print(tree.leftNode?.value)
print(tree.rightNode?.value)

print("<===============> 3層")
print(tree.rightNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.value)

print("<===============> 4層")
print(tree.rightNode?.rightNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.rightNode?.value)

print("<===============> 5層")
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.leftNode?.rightNode?.value)

print("<===============> 6層")
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.rightNode?.value)
print(tree.rightNode?.rightNode?.leftNode?.rightNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.leftNode?.rightNode?.rightNode?.value)

print("<===============> 7層")
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.rightNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.rightNode?.rightNode?.value)

print("<===============> 8層")
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.rightNode?.rightNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.rightNode?.rightNode?.rightNode?.value)

print("<===============> 9層")
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.rightNode?.rightNode?.rightNode?.leftNode?.value)
print(tree.rightNode?.rightNode?.leftNode?.leftNode?.rightNode?.rightNode?.rightNode?.rightNode?.value)

打印結(jié)果
<===============> 1層
1
<===============> 2層
nil
Optional(2)
<===============> 3層
nil
Optional(10)
<===============> 4層
Optional(8)
nil
<===============> 5層
Optional(3)
Optional(9)
<===============> 6層
nil
Optional(4)
nil
nil
<===============> 7層
nil
Optional(5)
<===============> 8層
nil
Optional(6)
<===============> 9層
nil
Optional(7)

獲取二叉樹(shù)的深度(層數(shù))

/// 二叉樹(shù)的深度
///
/// - Parameter rootNode: 二叉樹(shù)根節(jié)點(diǎn)
/// - Returns: 二叉樹(shù)的深度
class func depthOfTree(rootNode: BinaryTreeNode?) -> Int {
    if rootNode == nil {
        return 0
    }
    if rootNode?.leftNode == nil && rootNode?.rightNode == nil {
        return 1
    }
    
    // 左子樹(shù)深度
    let leftDepth = depthOfTree(rootNode: rootNode?.leftNode)
    // 右子樹(shù)深度
    let rightDepth = depthOfTree(rootNode: rootNode?.rightNode)
    
    return max(leftDepth, rightDepth) + 1
}

在合適的地方調(diào)用:

print("二叉樹(shù)深度\(BinaryTreeNode.depthOfTree(rootNode: tree))")
打印結(jié)果:
二叉樹(shù)深度9

按層遍歷

/// 二叉樹(shù)中某個(gè)位置的節(jié)點(diǎn)(按層次遍歷)
///
/// - Parameters:
///   - index: 按層次遍歷的位置
///   - rootNode: 根節(jié)點(diǎn)
/// - Returns: tree
class func treeNodeAtIndex(index: Int, rootNode: BinaryTreeNode?) -> BinaryTreeNode? {
    var index = index
    if index == 0 && rootNode == nil {
        return nil
    }
    // 數(shù)組當(dāng)成隊(duì)列
    var queueArray = [BinaryTreeNode?]()
    // 壓入根節(jié)點(diǎn)
    queueArray.append(rootNode!)
    while queueArray.count > 0 {
        let node = queueArray.first as? BinaryTreeNode
        if index == 0 {
            return node
        }
        // 彈出最前面的節(jié)點(diǎn),返照隊(duì)列先進(jìn)先出的原則
        queueArray.remove(at: 0)
        // 節(jié)點(diǎn)移除,index減少
        index -= 1
        if node?.leftNode != nil {
            queueArray.append(node?.leftNode)
        }
        if node?.rightNode != nil {
            queueArray.append(node?.rightNode)
        }
    }
    return nil
}

在合適的地方調(diào)用:

let indexNode = BinaryTreeNode.treeNodeAtIndex(index: 2, rootNode: tree)
print(indexNode?.value)

打印結(jié)果:
Optional(10)

前、中、后遍歷

/// 前序遍歷
/// 先訪問(wèn)根,再遍歷左子樹(shù),再遍歷右子樹(shù),典型的遞歸思想
/// - Parameters:
///   - rootNode: 樹(shù)
///   - handler: 回調(diào)數(shù)值
class func preOrderTraverseTree(rootNode: BinaryTreeNode? ,handler:@escaping (BinaryTreeNode) -> Void) {
    if rootNode != nil {
        handler(rootNode!)
        BinaryTreeNode.preOrderTraverseTree(rootNode: rootNode?.leftNode, handler: handler)
        BinaryTreeNode.preOrderTraverseTree(rootNode: rootNode?.rightNode, handler: handler)
    }
}

/// 中序遍歷
/// 先遍歷左子樹(shù),再訪問(wèn)根,再遍歷右子樹(shù)
/// - Parameters:
///   - rootNode: 樹(shù)
///   - handler: 回調(diào)數(shù)值
class func inOrderTreverseTree(rootNode: BinaryTreeNode? ,handler:@escaping (BinaryTreeNode) -> Void) {
    if rootNode != nil {
        BinaryTreeNode.preOrderTraverseTree(rootNode: rootNode?.leftNode, handler: handler)
        handler(rootNode!)
        BinaryTreeNode.preOrderTraverseTree(rootNode: rootNode?.rightNode, handler: handler)
    }
}

/// 后序遍歷
/// 先遍歷左子樹(shù),再遍歷右子樹(shù),在訪問(wèn)根
/// - Parameters:
///   - rootNode: 樹(shù)
///   - handler: 回調(diào)數(shù)值
class func postOrderTreverseTree(rootNode: BinaryTreeNode? ,handler:@escaping (BinaryTreeNode) -> Void) {
    if rootNode != nil {
        BinaryTreeNode.preOrderTraverseTree(rootNode: rootNode?.leftNode, handler: handler)
        BinaryTreeNode.preOrderTraverseTree(rootNode: rootNode?.rightNode, handler: handler)
        handler(rootNode!)
    }
}

在合適的地方調(diào)用:

// 前序遍歷
var dataArr1 = [Int]()
BinaryTreeNode.preOrderTraverseTree(rootNode: tree) { (treeNode) in
    dataArr1.append(treeNode.value)
}
print(dataArr1)


// 中序遍歷
var dataArr2 = [Int]()
BinaryTreeNode.inOrderTreverseTree(rootNode: tree) { (treeNode) in
    dataArr2.append(treeNode.value)
}
print(dataArr2)

// 后序遍歷
var dataArr3 = [Int]()
BinaryTreeNode.postOrderTreverseTree(rootNode: tree) { (treeNode) in
    dataArr3.append(treeNode.value)
}
print(dataArr3)

打印結(jié)果:
// 前序遍歷
[1, 2, 10, 8, 3, 4, 5, 6, 7, 9]
// 中序遍歷
[1, 2, 10, 8, 3, 4, 5, 6, 7, 9]
// 后續(xù)遍歷
[2, 10, 8, 3, 4, 5, 6, 7, 9, 1]

持續(xù)更新中~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 樹(shù)的概述 樹(shù)是一種非常常用的數(shù)據(jù)結(jié)構(gòu),樹(shù)與前面介紹的線性表,棧,隊(duì)列等線性結(jié)構(gòu)不同,樹(shù)是一種非線性結(jié)構(gòu) 1.樹(shù)的定...
    Jack921閱讀 4,491評(píng)論 1 31
  • 定義 一個(gè)有窮的結(jié)點(diǎn)集合,可以為空。若不為空,則它是由根結(jié)點(diǎn)和稱(chēng)為其左子樹(shù)和右子樹(shù)的兩個(gè)互不相交的二叉樹(shù)組成。 二...
    IAM四十二閱讀 2,621評(píng)論 0 2
  • 二叉樹(shù) 在計(jì)算機(jī)科學(xué)中,二叉樹(shù)是每個(gè)節(jié)點(diǎn)最多有兩個(gè)子樹(shù)的樹(shù)結(jié)構(gòu)。通常子樹(shù)被稱(chēng)作“左子樹(shù)”和“右子樹(shù)”,左子樹(shù)和右子...
    靜默加載閱讀 2,060評(píng)論 0 3
  • 一直以來(lái),我都很少使用也避免使用到樹(shù)和圖,總覺(jué)得它們神秘而又復(fù)雜,但是樹(shù)在一些運(yùn)算和查找中也不可避免的要使用到,那...
    24K男閱讀 6,783評(píng)論 5 14
  • 九月這是個(gè)過(guò)分涼爽的九月,可氣的,一號(hào)到現(xiàn)在了感冒還沒(méi)好。每每同事勸說(shuō)吃藥的時(shí)候,總會(huì)以“是藥三分毒啊”這樣的“真...
    Youhoo丶閱讀 258評(píng)論 0 0