二叉树遍历

2013年10月18日

前序和后序函数是树结构上的简单递归函数;请注意,我们小心避免树结构中出现空值:

(定义(预订单t)
(如果(null?t)
(列表)
(附加(列表(汽车))
(如果(配对?(cdr t))
(预订单(cadr t))
(列表)
(如果(和(配对?(cdr t))
(配对?(cddr t))
(预订单(caddr t))
(列表))

(定义(订单后t)
(如果(null?t)
(列表)
(追加(if(配对?(cdr t))
(后期订单(cadr t))
(列表)
(如果(和(配对?(cdrt))
(配对?(cddr t))
(后序(caddr t))
(列表)
(列表(汽车t)))

以下是应用于上一页所示示例树的函数:

>(定义t'(8(3(1)(6(4)(7)))(10()(14(13)())))
>(预订单t)
(8 3 1 6 4 7 10 14 13)
>(订单后t)
(1 4 7 6 3 13 14 10 8)

重建树是遍历树的相反操作。预购序列最左边的元素是树的根。小于根的节点位于树的左侧子级,大于根的节点则位于树的右侧子级,因此该解决方案使预排序序列中的第一个节点成为树的根,并在序列的较小部分和较大部分递归调用自身。基于后序序列重建树则相反,树的根位于列表的最后一个元素:

(定义(预构建xs)
(cond((null?xs)(列表))
((null?(cdr xs))(list(car xs))
(else(带值的调用
(λ()
(分时
(λ(x)(<x(汽车x)))(cdr x))
(λ(lo-hi)
(列表(汽车xs)(预制lo)(预制hi)))

(定义(构建后xs)
(cond((null?xs)(列表))
((空?(cdr-xs))(列表(汽车xs)
(else(带值的调用
(λ()
(分时
(λ(x)(<x(最后一个xs)))
(λ(lo-hi)
(列表(最后一个xs)(构建后lo)(构建之后hi))))

我们使用便利功能最后的but-last公司:

(定义(最后一个xs)(汽车(反向xs))

(define(but-last xs)(反向(cdr(反向xs)))

以下是更多示例:

>(预构建(预订单t))
(8 (3 (1) (6 (4) (7))) (10 () (14 (13) ())))
>(后生成(后排序t))
(8 (3 (1) (6 (4) (7))) (10 () (14 (13) ())))

我们使用分裂时期来自标准前奏曲。您可以在运行程序http://programmingpraxis.codepad.org/s86rBxGF.

页:1 2

9对“二叉树遍历”的回应

  1. 我的前两个函数的解决方案,用105字节的JavaScript编写:

    //排序函数
    //参数:源树、目标数组、方向(前:1,后:0)
    o=函数(b,c,d){void 0!==b&&(isNaN(b)

    //测试
    树=[[1,3,[4,6,7]],8,[,10,[13,14,]]];
    pre_order_array=[];
    post_order_array=[];

    o(树,pre_order_array,1);
    console.log(pre_order_array);//->[8, 1, 4, 7, 6, 3, 13, 14, 10]

    o(树,post_order_array,0);
    console.log(post_order_array);//->[1, 4, 7, 6, 3, 13, 14, 10, 8]

  2. 对不起,我的意思是:

    o=函数(b,c,d){void 0!==b&&(isNaN(b)

    此函数用于返回预订单的正确数组。

  3. 彼得·萨尔维

    通用Lisp解决方案:

    ;;; 节点;(值左向右)(取消预订(树)(当树(cons(第一棵树)(append(preorder(第二棵树)))(删除后序(树)(当树(追加(后序(第二棵树))(撤资树插入(树a)(if(空树)(列出nil-nil)(第二棵树)((<a(第一棵树))(列表(第一棵树)(树插入(第二棵树)a)(第三棵树))(t(列表(第一棵树)(第二棵树)(从前序(lst)中删除树(减少#’tree-insert lst:初始值nil)(从postdorder(lst)中拆除树(减少#'tre-insert(反向lst):初始值为零)
  4. 结构ListX=结构趣味跨度f[]=([],[])|跨度f(x::xs)=如果f x然后val(ys,zs)=span f xs在里面(x::ys,zs)结束其他的([],x::xs)fun splitAtLast[]=提升列表。清空|最后[x]处的拆分=([],x)|最后拆分(x::xs)=val(ys,y)=拆分到最后一个xs在里面(x::ys,y)结束结束datatype“树=一棵树一棵树|MTTree(MTTree)fun遍历f g e MTTree=e|遍历f g e(树(a,l,r))=g(f a)(横移f g e l)(横切f g e r)趣味预赛=fun g e ls rs=e::(ls@rs码)在里面横向(fn x=>x)g[]t结束有趣的帖子t=乐趣ls rs=(ls@rs码)@[英]在里面导线(fn x=>x)g[]t结束数据类型遍历=前|后地方的fun-root-Pre(x::xs)=(xs,x)|root Post xs=ListX.splitAtLast xs在里面有趣的侦察_[]=MTTree|侦察t xs=val(ys,y)=根t xsval(l,r)=列表X.span(fn a=>a<y)ys在里面树(y,侦察t l,侦察t r)结束结束val a=预(侦察预[8、3、1、6、4、7、10、14、13])= [8, 3, 1, 6, 4, 7, 10, 14, 13]val b=岗位(侦察岗位[1、4、7、6、3、13、14、10、8])= [1, 4, 7, 6, 3, 13, 14, 10, 8]
  5. 约瑟夫·斯文宁森

    对于从预订单遍历中重新创建树的任务,我设法想出了一个函数,它遍历列表一次,除了树之外不分配任何额外的东西(好吧,它确实分配了元组,但它们可以被删除)。这很好,但我没有对postorder遍历做同样的事情。

    fromPreOrder::Ord a=>[a]->树fromPreOrder[]=叶fromPreOrder(a:as)=分支a l(from PreOrder bs)哪里(l,bs)=小于a小于n[]=(叶,[])lessThan n all@(a:as)|a>=n=(叶,全部)|否则=(分支a l r,cs)其中(l,bs)=小于a(r,cs)=小于n bs
  6. 在xquery中:

    声明函数local:post-order(
    $tree作为节点()
    ) {
    让$seq:=
    if(local:has-children($tree))然后(
    让$left:=$tree/node()[1]
    让$right:=$tree/node()[2]
    返回
    (
    本地:后期订单($left),
    本地:后期订单($right),
    $tree/@val/fn:string()
    )
    )其他(
    $tree/@val/fn:string()
    )
    返回$seq
    };

    声明函数local:预排序(
    $tree作为节点()
    ) {
    让$seq:=
    if(local:has-children($tree))然后(
    让$left:=$tree/node()[1]
    让$right:=$tree/node()[2]
    返回
    (
    $tree/@val/fn:string(),
    本地:预订单($left),
    本地:预订单($right)
    )
    )其他(
    $tree/@val/fn:string()
    )
    返回$seq
    };

    声明函数local:has-children(
    $node作为node()*
    ) {
    如果(fn:count($node)gt 1),则(
    fn:error(xs:QName(“error”),“不是单个节点”)
    )其他(
    如果($node/node()),则(
    fn:true()
    )其他(
    fn:假()
    )
    )
    };

    让$tree:=

    返回

    {local:预排序($tree)}
    {local:后序($tree)}

  7. 我的格式很明显变了…。但是函数是正确的

  8. 树木

    祝贺Josef Sveningsson找到O(n)预构建!它生成的树与指定的格式不太匹配,但很容易编写一个函数将其转换为一个在其叶子中存储内容的树,所以这没什么大不了的。后期构建似乎天生就比较困难。我觉得应该可以编写一些与prebuild非常类似的东西来应用于反向的post-order遍历,但我还没有成功地实现它。我稍后再试试。

  9. […]提交给Programming Praxis的这个文件提供了一个O(n)函数,它可以“撤消”二进制搜索树的预先排序遍历,将列表转换回树。提供缺少的数据声明:[…]

留下评论