课程回顾

Swarthmore学院16年开的编译系统课,总共10次大作业。本随笔记录了相关的课堂笔记以及第2大次作业。

比较两个lists的逻辑:

  1. let rec cmp l ll =
  2. match (l,ll) with
  3. | [], [] -> 0
  4. | [],_ -> -1
  5. | _,[] -> 1
  6. | (h::t), (hh::tt) -> if h > hh then 1
  7. else if h < hh then -1
  8. else cmp t tt;;

编程作业

1. 平衡二叉树(AVL tree)

  • 一颗AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)。

    在进行插入时,有四种情况会破坏树的平衡性质,需要通过相应的旋转操作来恢复树的平衡。这四种情况如下所示:

    • 情况一:对左儿子的左子树进行一次插入(通过单旋转恢复平衡)

if k2左子树高度 - k2右子树高度 = 2 > 1 then

  RotateLeft k2: Node(k2, Node(k1, X, Y), Z) -> Node(k1, X, Node(k2, Y, Z))

  • 情况二:对左儿子的右子树进行一次插入(通过双旋转恢复平衡)

if k3左子树高度 - k3右子树高度 = 2 > 1 then

  if k1左子树高度 - k1右子树高度 = -1 < 0 then

    RotateRight k1: Node(k1, A, Node(k2, B, C)) -> Node(k2, Node(k1, A, B), C)

  RotateLeft k3: Node(k3, Node(k2, Node(K1, A, B), C), D) -> Node(k2, Node(k1, A, B), Node(k3, C, D))

  • 情况三:对右儿子的左子树进行一次插入 (和情况二镜像对称)

  • 情况四:对右儿子的右子树进行一次插入 (和情况一镜像对称)

上面的情况一和情况二的if条件可以合并一下,同理适用于情况三和情况四,分析清楚后就有了下面的代码:

  1. type ('k, 'v) avlnode =
  2. | Leaf
  3. | Node of int * 'k * 'v * ('k, 'v) avlnode * ('k, 'v) avlnode
  4. let height (n : ('k, 'v) avlnode) : int =
  5. match n with
  6. | Leaf -> -1
  7. | Node(h, _, _, _, _) -> h
  8. let create k v l r =
  9. Node(1 + max (height l) (height r), k, v, l, r)
  10. let rotate_left n =
  11. let k,v,l,r = get_elems n in
  12. let lk,lv,ll,lr = get_elems l in
  13. create lk lv ll (create k v lr r)
  14. let rotate_right n =
  15. let k,v,l,r = get_elems n in
  16. let rk,rv,rl,rr = get_elems r in
  17. create rk rv (create k v l rl) rr
  18. let balance (n : ('k, 'v) avlnode) : ('k, 'v) avlnode =
  19. let k,v,l,r = get_elems n in
  20. if (height l)-(height r) > 1 then
  21. let _, _, ll, lr = get_elems l in
  22. rotate_left (
  23. if (height ll)-(height lr) < 0 then
  24. create k v (rotate_right l) r
  25. else n
  26. )
  27. else if (height l)-(height r) < -1 then
  28. let _, _, rl, rr = get_elems r in
  29. rotate_right (
  30. if (height rl)-(height rr) > 0 then
  31. create k v l (rotate_left r)
  32. else n
  33. )
  34. else n
  35. let rec set (n : ('k, 'v) avlnode) (key : 'k) (value : 'v) : ('k, 'v) avlnode =
  36. match n with
  37. | Leaf -> create key value Leaf Leaf
  38. | Node(_, k, v, l, r) ->
  39. balance (
  40. if k = key then create key value l r
  41. else if key < k then create k v (set l key value) r
  42. else create k v l (set r key value)
  43. )
  44. let add_all (n : ('k, 'v) avlnode) (keys : ('k * 'v) list) : ('k, 'v) avlnode =
  45. List.fold_left (fun a (k, v) -> set a k v) n keys

2. 表达式求值

  • 这里定义了一个算数类型,

    例如表达式:

      5 * 3 + y

    可以表示为:

      Plus(Times(Num(5), Num(3)), Variable("y"))
  1. type arith =
  2. | Plus of arith * arith
  3. | Times of arith * arith
  4. | Variable of string
  5. | Num of int
  • 实现了一个方法计算表达式的值,

    例如执行:

      evaluate (Times(Plus(Variable("x"), Variable("y")), Num(5))) (add_all Leaf [("x", 5); ("y", 7)])

    会返回:

      60
  1. let rec evaluate (a : arith) (vars : (string, int) avlnode) : int =
  2. let get_variable_value (key : string) (value : int option) : int =
  3. match value with
  4. | Some(num) -> num
  5. | None -> failwith ("Variable " ^ key ^ " is not contained in vars in the expression")
  6. in
  7. match a with
  8. | Plus(l, r) -> (evaluate l vars) + (evaluate r vars)
  9. | Times(l, r) -> (evaluate l vars) * (evaluate r vars)
  10. | Variable(var) -> get_variable_value var (get vars var)
  11. | Num(num) -> num
  • 实现一个方法把算数类型解析成数学表达式,

    例如执行:

      pretty (Plus(Plus(Times(Plus(Num(5), Variable("y")), Variable("x")), Num(2)), Num(1)))

    会返回:

      (5 + y)x + 2 + 1
  1. let rec pretty (a : arith) : string =
  2. let rec helper (a: arith) : string =
  3. match a with
  4. | Plus(_) -> "(" ^ pretty a ^ ")"
  5. | _ -> pretty a
  6. in
  7. match a with
  8. | Plus(l, r) -> pretty l ^ " + " ^ pretty r
  9. | Times(l, r) -> helper l ^ helper r
  10. | Variable(var) -> var
  11. | Num(num) -> string_of_int num

3. 测试用例

  • 省略了一些test case,仅演示用法
  1. let t_any name value expected = name>::
  2. (fun _ -> assert_equal expected value ~printer:dump);;
  3. let a_tree = Node(0, "a", 5, Leaf, Leaf);;
  4. let get_tests = [
  5. t_any "get1" (get a_tree "a") (Some(5));
  6. t_any "get2" (get (Node(0, "b", 15, a_tree, Leaf)) "a") (Some(5));
  7. t_any "get3" (get (Node(0, "b", 15, a_tree, Leaf)) "c") None;
  8. ];;
  9. let evaluate_tests = [
  10. t_any "evaluate1" (evaluate (Times(Plus(Variable("x"), Variable("y")), Num(5))) (add_all Leaf [("x", 5); ("y", 7)])) 60;
  11. ];;
  12. let pretty_tests = [
  13. t_any "pretty1" (pretty (Plus(Plus(Times(Plus(Num(5), Variable("y")), Variable("x")), Num(2)), Num(1)))) "(5 + y)x + 2 + 1";
  14. ];;
  15. let all_tests =
  16. get_tests @
  17. evaluate_tests @
  18. pretty_tests
  19. ;;
  20. let suite = "suite">:::all_tests;;
  21. run_test_tt_main suite
  • @函数的定义为:

val append : 'a list -> 'a list -> 'a list

Concatenate two lists. Same as the infix operator @. Not tail-recursive (length of the first argument).

参考资料

Lab 1 — OCaml Tree Programming

[swarthmore cs75] Lab 1 — OCaml Tree Programming的更多相关文章

  1. [swarthmore cs75] Lab 0 Warmup & Basic OCaml

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第1次大作业. 什么是编译 编译就是执行Program->Program'转换的过程,如下 ...

  2. [swarthmore cs75] Compiler 4 – Diamondback

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第6次大作业. 函数声明 增加函数声明.函数调用的抽象语法:在转换成anf之前还要检查函数声明和 ...

  3. [swarthmore cs75] Compiler 2 – Boa

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第4次大作业. A-Normal Form 在80年代,函数式语言编译器主要使用Continua ...

  4. [swarthmore cs75] Compiler 1 – Adder

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第3次大作业. 编译的过程:首先解析(parse)源代码,然后成抽象语法树(AST),再生成汇编 ...

  5. [swarthmore cs75] inlab1 — Tiny Compiler

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了inlab1的实践过程. tiny compiler 这个迷你的编译器可以将一个源文件,编译成可执行的二进制代码. ...

  6. [swarthmore cs75] Compiler 6 – Garbage Snake

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第9次大作业. 赋值的副作用:循环元组 下面的代码展示了Python3是如何处理循环列表(pri ...

  7. [swarthmore cs75] Compiler 6 – Fer-de-lance

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第8次大作业. First-class function: It treats function ...

  8. [swarthmore cs75] Compiler 5 – Egg-eater

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第7次大作业. 抽象语法: 存储方式: 栈中的数据如果最后三位(tag bits)是001表示元 ...

  9. [swarthmore cs75] Compiler 3 – Cobra

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第5次大作业. 增加了bool数据表示和比较运算符的支持,具体语法参考下图: 第一种int和bo ...

随机推荐

  1. Jquery中小数取整

    var uu=Math.floor(5.36) 向下取整 结果为5 var uu=Math.floor(5.88) 结果为5 Math.ceil(5.33) 向上取整,结果为6 Math.round( ...

  2. 3D Math Keynote 4

    [3D Math Keynote 4] 1.三角带. 合并三角带能够提升渲染效率. 三角扇. 2.边缩坍,将边缩减为顶点 . 网格消减,使用边缩坍,可以实现渐进式网络. 3.下图左边是面拆分.右边是焊 ...

  3. java operate

    class OperateDemo { public static void main(String[] args) { /* + - * / %(取余数) */ int x = 2810; Syst ...

  4. python2与python3的区别

    print 函数(Python3中print为一个函数,必须用括号括起来:Python2中print为class)在Python 2.6与Python 2.7里面,以下三种形式是等价的: print ...

  5. del_cursor 批量删除游标

    declare   cursor [del_cursor] is select a.*, a.rowid row_id from [table_name] a order by a.rowid;   ...

  6. es6数组的扩展

    数组扩展运算符 ...(三个点) const demoArr=[0,1,2,3,4] console.log(...demoArr) // 0 1 2 3 4 // 他把一个数组用逗号分隔了出来 // ...

  7. Taro-ui TabBar组件使用路由跳转

    1. 安装taro-ui (此处使用cnpm) cnpm install taro-ui 2. 全局引入样式 app.scss sass :@import "~taro-ui/dist/st ...

  8. 更换Appsecrect应该要注意的问题

    1. 有时候因为需要,有些地方需要填写Appsecrect, 但是大家都知道微信公众平台上这个值 即使你自己是管理员是看不到的,只能重置,但是重置后,一定要记住刷新AccessToken啊,不然就尴尬 ...

  9. web 文件上传的几种方式

    问题 文件上传在WEB开发中应用很广泛. 文件上传是指将本地图片.视频.音频等文件上传到服务器上,可以供其他用户浏览或下载的过程. 以下总结了常见的文件(图片)上传的方式和要点处理. 表单上传 这是传 ...

  10. python课程安排

    作为最流行的脚本语言之一,python具有内置的高级数据结构和简单面向对象编程思想实现.同时,其语法简洁而清晰,类库丰富而强大,非常适合进行快速原型开发.另外,python可以运行在多种系统平台下,从 ...