【Scala筆記——道】Scala Tree Fold深度優先遍歷詳解

Tree 定義

簡化定義Scala Tree結構,包含兩個部分: Branch和Tree。爲了簡化數據結構,Branch只包含 Tree類型的 左節點 和 右節點, Leaf包含具體 Valuecss

sealed trait Tree[+A]

case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]

深度優先遍歷 DFS

樹的遍歷右兩種方式:
- 深度優先
- 廣度優先
這裏用DFS 實現,深度優先搜索屬於圖算法的一種,英文縮寫爲DFS即Depth First Search,其過程簡要來講是對每個可能的分支路徑深刻到不能再深刻爲止,並且每一個節點只能訪問一次。python

具體搜索順序能夠參考附圖
1. 搜索根節點 左子樹
2. 搜索當前樹的左子樹
3. 搜索當前樹的左子樹
4. 返回父節點,搜索父節點 右子樹
5. 搜索當前樹的左子樹
6. 返回父節點,搜索父節點 右子樹
7. 返回父節點, 返回父節點,返回父節點,搜索右子樹
8. ….算法

DFS

咱們從一道題來熟悉Scala遍歷操做,求Scala樹中節點總數
按照DFS 思想實現代碼以下數據結構

def countNodes[A](tree: Tree[A]): Int = {
    def go[A](tree: Tree[A], sum: Int): Int = tree match {
      case Leaf(v) => sum + 1       //葉子節點 sum+1
      case Branch(left, right) => sum + 1 + go(left, 0) + go(right, 0)  //分支節點 sum = sum + 1 + 左子樹節點總數 + 右子樹節點總數
      case _ => 0
    }
    go(tree, 0) //遞歸
  }

結合【Scala筆記——道】Scala List HOF foldLeft / foldRight 中講到的List fold思想函數

咱們將countNode 方法的遍歷進行抽象化
,首先一個函數最重要的就是輸入 / 輸出,參考List fold,不難理解對Tree的函數操做必然是將Tree[A]轉化爲 [B],咱們這裏實現的簡化樹模型中,Value的具體存儲都在葉子節點中,所以測試

def deepFirstSearch[A, B](tree: Tree[A])(f: A => B)...  = tree match {
      case Leaf(value) => f(value)
      ...
  }

其次,將DFS 搜索的過程進行抽象。對每個 枝點,首先搜索 枝點的左節點,獲得左節點執行結果之後,再搜索右節點,獲得右節點執行結果之後,執行 對左右子樹 函數結果的 函數操做,所以spa

def deepFirstSearch[A, B](tree: Tree[A])(f: A => B)(g: (B, B) => B) : B  = tree match {
      case Leaf(value) => f(value)
      case Branch(l, r) => g( deepFirstSearch(l), deepFirstSearch(r) )
  }

使用

經過幾個小例子來實踐deepFirstSearch.net

獲取Tree[Int]中最大值scala

def maximum(tree: Tree[Int]): Int =
    deepFirstSearch(tree)(l => l)(_ max _)

求樹的最大深度3d

def depth[A](tree: Tree[A]): Int =
    deepFirstSearch(tree)(_ => 1)(_.max(_) + 1)

MAP函數 將A 轉化爲B

def map[A, B](tree: Tree[A])(f: A => B): Tree[B] = {
    deepFirstSearch(tree)( x => (Leaf(f(x)): Tree[B]))( (a, b) => Branch(a, b))

測試以下

def main(args: Array[String]): Unit = {

    val tree = Branch(
                  Branch(
                    Branch
                      (Leaf(1),
                        Branch(
                          Leaf(7),
                          Branch(
                            Leaf(8),
                            Leaf(9)
                          ))),
                    Branch(
                      Leaf(34), Leaf(4))),
                  Branch(
                    Leaf(5), Leaf(6)))

    println("Max value :" + maximum(tree))

    println("Depth :" + depth(tree))

    println("Map :" + map(tree)(x => if(x%2 == 0) Branch(Leaf(1), Leaf(2)) else x))
  }

結果以下

Max value :34
Depth :6
Map :Branch(Branch(Branch(Leaf(1),Branch(Leaf(7),Branch(Leaf(Branch(Leaf(1),Leaf(2))),Leaf(9)))),Branch(Leaf(Branch(Leaf(1),Leaf(2))),Leaf(Branch(Leaf(1),Leaf(2))))),Branch(Leaf(5),Leaf(Branch(Leaf(1),Leaf(2)))))
相關文章
相關標籤/搜索