【问题标题】:converting string list to ternary tree in sml在sml中将字符串列表转换为三叉树
【发布时间】:2014-06-24 21:20:00
【问题描述】:

我想将一个字符串列表转换成三叉树。该树应该具有以下数据类型

datatype ttree = node of string*ttree list*string|leaf of string*string*string

例如,

["<root>","<a3>","<b2>","Father","</b2>","<b3>","Mother","</b3>","</a3>","<a1>","<ffx>","AAA",...] : string list

应该转换成

val test = 
node
("<root>",
 [node
    ("<a3>",
     [leaf ("<b2>","Father","<b2>"),leaf ("<b3>","Mother","<b3>")],
     "<a3>"),
  node
    ("<a1>",[leaf ("<ffx>","AAA","<ffx>"),leaf ("<ff>","BBB","<ff>")],
     "<a1>")],"<root>") : ttree

【问题讨论】:

  • fun listToTree nil = node("",[],"") | listToTree (x::xs) = let val n = length(xs)-1 val l = List.last xs val dx = List.take(xs,n) in node(x,listToTree(dx),l) end; 这是我的想法,但看起来太天真了,没有做我想做的事@Tayacan
  • 您将需要一个帮助函数,该函数知道您当前在“内部”哪个标签,但您不需要lengthtakelast

标签: xml-parsing tree sml smlnj


【解决方案1】:

不是最有效的解决方案,但这应该可以解决问题:

datatype ttree = node of string*ttree list*string | leaf of string*string*string

val l = ["<root>",
          "<a3>",
            "<b2>","Father","</b2>",
            "<b3>","Mother","</b3>",
          "</a3>",
          "<a1>",
            "<ffx>","AAA","</ffx>",
          "</a1>"]

(*listToTree(l) = string list to ternary tree*)
fun listToTree(l : string list) : ttree =
  let
    (*isLeaf(s1, s3) = true if s1=<a> and s3=</a>, 
                        a can be replaced with anything
                       false otherwise*)
    fun isLeaf(s1 : string, s3 : string) : bool =
      let
        val (e1, e3) = (explode s1, explode s3)
        val (t1c1::t1) = e1
        val t1e = List.last t1
        val (t3c1::t3c2::t3) = e3
        val t3e = List.last t3
      in
        if t1c1 = #"<" andalso 
           t1c1 = t3c1 andalso 
           t1e = #">"  andalso
           t1e = t3e   andalso
           t3c2 = #"/" andalso
           t1 = t3     then true else false
      end

    (*parseUntil(l, until, acc) = (p, r),
      where p = acc + a part of l until an element x 
                that satisfies isLeaf(until,x)
        and r = elements of list l after x *)
    fun parseUntil(l : string list, until : string, acc : string list)
           : string list * string list =
      case l of
          []    => (rev acc, [])
        | x::xs => if isLeaf(until, x) 
                   then (rev acc, xs) 
                   else parseUntil(xs, until, x::acc)

    (*parseList(l) = the ttree list of the given string list*)
    fun parseList(l : string list) : ttree list =
      case l of
          [] => []
        | x::xs => let
          val (parsed, rest) = parseUntil(xs, x, [])
        in
          if length parsed = 1 
          then leaf(x, hd xs, x)::parseList(rest)
          else node(x, parseList(parsed), x)::parseList(rest)
        end
  in
    hd (parseList l)
  end

val result = listToTree l;

基本上就是这样做的:

  • 一旦你得到一个标签,获取列表元素直到结束标签。

  • 调用与元素相同的解析器函数,直到结束标记,并将结果放入节点中的列表中。

  • 使用关闭标记后的元素调用相同的解析器函数,并将它们追加到上一级列表中。

希望我能帮上忙。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多