zoukankan      html  css  js  c++  java
  • 泛函编程(8)-数据结构-Tree

        上节介绍了泛函数据结构List及相关的泛函编程函数设计使用,还附带了少许多态类型(Polymorphic Type)及变形(Type Variance)的介绍。有关Polymorphism的详细介绍会放在typeclass讨论中。为了更多了解泛函数据结构(Functional Data Structure),想在这个章节把另一个我们熟悉的数据结构-Tree做些简单介绍。

        Tree的状态不是枝(Branch)就是叶(Leaf),这个很容易理解。那么就按照上节设计List那样设计Tree类型:

    1   trait Tree[+A] 
    2   case class Leaf[A](value: A) extends Tree[A]
    3   case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]

    类参数+A代表协变(covariant),这个在上节List中已经介绍过了。先创建一个Tree实例(Tree Instance):

    1  val tree = Branch(Branch(Leaf(1),Leaf(2)),Branch(Branch(Leaf(10),Leaf(8)),Leaf(3)))
    2                                                   //> tree  : ch3.tree.Branch[Int] = Branch(Branch(Leaf(1),Leaf(2)),Branch(Branch(
    3                                                   //| Leaf(10),Leaf(8)),Leaf(3)))

    创建了一个Tree Instance tree,如下图:

    数数有几个节点:

    1       def size: Int = this match {
    2           case Leaf(_) => 1
    3           case Branch(l,r) => 1 + l.size + r.size
    4       }
    1   tree size                                       //> res0: Int = 9

    这是所有branch + leaf 总数。

    分开计算branch 和 leaf 数量:

    1       def countLeafs: Int = this match {
    2           case Leaf(_) => 1
    3           case Branch(l,r) => 0 + l.size + r.size
    4       }
    5        def countBranches: Int = this match {
    6           case Leaf(_) => 0
    7           case Branch(l,r) => 1 + l.size + r.size
    8       }
    9  
    1   tree.countLeafs                                 //> res1: Int = 8
    2   tree.countBranches                              //> res2: Int = 9

    探探最深有多深:

    1       def depth: Int = this match {
    2           case Leaf(_) => 0
    3           case Branch(l,r) => 1 + (l.depth max r.depth)
    4       }
    1   tree depth                                      //> res1: Int = 3

    找出最大值的Leaf:

    1       def maxValue: Int = this match {
    2           case Leaf(a: Int) => a
    3           case Branch(l,r) => l.maxValue max r.maxValue
    4       }
    1  tree maxValue                                   //> res2: Int = 10

    可以从以上这些函数得出一下共性。把共性抽象出来用fold来实现:

    1         def fold[B](f: A => B)(g: (B,B) => B): B = this match {
    2             case Leaf(n) => f(n)
    3             case Branch(l,r) => g(l.fold(f)(g), r.fold(f)(g))
    4         }

    函数fold分别收到两个方法f,g:f用来处理Leaf,g用来处理Branch。看看用fold来实现上面的函数:

    1         def sizeByfold = fold(a => 1)(1 + _ + _)
    2         def maxValueByfold(l: Tree[Int]) = l.fold(a => a)((x,y) => 0 + (x max y))
    3         def depthByfold = fold(a => 0)((x,y) => 1 + (x max y))
    1   tree sizeByfold                                 //> res3: Int = 9
    2   
    3   tree depthByfold                                //> res4: Int = 3
    4   
    5   tree.maxValueByfold(tree)                       //> res5: Int = 10

     可能这个 tree.maxValueByfold(tree) 有点怪,但如果把函数实现放到 object Tree里然后import Tree._就可以了。

    下面把map和flatMap实现了:

    1       def map[B](f: A => B): Tree[B] = this match {
    2           case Leaf(a) => Leaf(f(a))
    3           case Branch(l,r) => Branch(l.map(f),r.map(f))
    4       }
    5       def flatMap[B](f: A => Tree[B]): Tree[B] = this match {
    6           case Leaf(a) => f(a)
    7           case Branch(l,r) => Branch(l.flatMap(f), r.flatMap(f))
    8       }

     

     

  • 相关阅读:
    WEB安全第二篇--用文件搞定服务器:任意文件上传、文件包含与任意目录文件遍历
    WEB安全第一篇--对服务器的致命一击:代码与命令注入
    python的内存管理与垃圾回收机制学习
    java反序列化漏洞的检测
    python epoll实现异步socket
    Python class的属性访问控制和内建函数重写实现高级功能以及@property
    weblogic新漏洞学习cve-2017-10271
    PHP后门的eval类和system类 函数到底有哪些区别
    JS 转整型
    .NET MVC model数据验证
  • 原文地址:https://www.cnblogs.com/tiger-xc/p/4332020.html
Copyright © 2011-2022 走看看