在Fsharp F#中递归遍历二叉树的三种方法

时间:2016-01-19 08:24:45

标签: types tree f#

我一直在阅读这本伟大的书使用F#进行功能编程我刚刚进入有限树的章节,我注意到有三种遍历树的方法,但我不明白为什么以及它们如何不同。 这是代码。

type BinaryTree<'a> =
    |Leaf 
    |Node of BinaryTree<'a> * 'a * BinaryTree<'a>


let rec preorder (tr:BinaryTree<'a>) : 'a list =
    match tr with
    |Leaf            -> []
    |Node(trr,x,trl) -> x:: (preorder trr) @ (preorder trl) 


let rec inorder (tree:BinaryTree<'a>) : 'a list =
    match tree with
    |Leaf -> []
    |Node(tr,x,tl) -> (inorder tr) @ [x] @ (inorder tl)

let rec postorder (tree:BinaryTree<'a>) : 'a list =
    match tree with
    |Leaf -> []
    |Node(tr,x,tl) -> (postorder tr) @ (postorder tl) @ [x]

let someTree = Node(Leaf,20,Node(Leaf,40,Node(Node(Leaf,-2,Leaf),2,Node(Leaf,0,Leaf))))

preorder someTree
inorder someTree
postorder someTree

欢迎任何帮助! :)

2 个答案:

答案 0 :(得分:2)

查看不同遍历方法中连接顺序的顺序:

上一页:x :: (preorder tl) @ (preorder tr)

  1. x:当前值
  2. preorder tl:访问左树
  3. preorder tr:访问右树
  4. 在:(inorder tl) @ [x] @ (inorder tr)

    1. inorder tl:访问左树
    2. x:当前值
    3. inorder tr:访问右树
    4. 发布:(postorder tl) @ (postorder tr) @ [x]

      1. postorder tl:访问左树
      2. postorder tr:访问右树
      3. x:当前值
      4. 如果从顶部(根部上方)开始沿逆时针方向追踪树木:

        • 预先遍历遍历按照您首先遇到每个节点左侧的顺序返回元素。
        • 有序遍历按照您首先遇到每个节点底部的顺序返回元素。
        • 订单后遍历会按照您首先遇到每个节点右侧的顺序返回元素。

        作为简要概述,预订遍历对于复制整个树非常有用,有序行程对于二进制搜索很有用,而后序遍历对于删除整个树非常有用。

        可在此处找到更多详细信息:https://en.wikipedia.org/wiki/Tree_traversal

答案 1 :(得分:0)

如果您运行自己的代码,您将看到结果的差异:

> preorder someTree;;
val it : int list = [20; 40; 2; -2; 0]
> inorder someTree;;
val it : int list = [20; 40; -2; 2; 0]
> postorder someTree;;
val it : int list = [-2; 0; 2; 40; 20]

因此,区别在于列表元素的顺序。